|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the ActiveQt framework of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:BSD$ |
|
10 ** You may use this file under the terms of the BSD license as follows: |
|
11 ** |
|
12 ** "Redistribution and use in source and binary forms, with or without |
|
13 ** modification, are permitted provided that the following conditions are |
|
14 ** met: |
|
15 ** * Redistributions of source code must retain the above copyright |
|
16 ** notice, this list of conditions and the following disclaimer. |
|
17 ** * Redistributions in binary form must reproduce the above copyright |
|
18 ** notice, this list of conditions and the following disclaimer in |
|
19 ** the documentation and/or other materials provided with the |
|
20 ** distribution. |
|
21 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor |
|
22 ** the names of its contributors may be used to endorse or promote |
|
23 ** products derived from this software without specific prior written |
|
24 ** permission. |
|
25 ** |
|
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
|
37 ** $QT_END_LICENSE$ |
|
38 ** |
|
39 ****************************************************************************/ |
|
40 |
|
41 #define QT_NO_CAST_TO_ASCII |
|
42 |
|
43 #ifndef QT_NO_WIN_ACTIVEQT |
|
44 |
|
45 #include <qabstracteventdispatcher.h> |
|
46 #include <qapplication.h> |
|
47 #include <qbuffer.h> |
|
48 #include <qdatastream.h> |
|
49 #include <qdebug.h> |
|
50 #include <qevent.h> |
|
51 #include <qeventloop.h> |
|
52 #include <qfile.h> |
|
53 #include <qpointer.h> |
|
54 #include <qhash.h> |
|
55 #include <qmap.h> |
|
56 #include <qmenubar.h> |
|
57 #include <qmenu.h> |
|
58 #include <qmetaobject.h> |
|
59 #include <qpixmap.h> |
|
60 #include <qstatusbar.h> |
|
61 #include <qwhatsthis.h> |
|
62 #include <ocidl.h> |
|
63 #include <olectl.h> |
|
64 #include <private/qcoreapplication_p.h> |
|
65 |
|
66 #include "qaxfactory.h" |
|
67 #include "qaxbindable.h" |
|
68 #include "qaxaggregated.h" |
|
69 |
|
70 #include "../shared/qaxtypes.h" |
|
71 |
|
72 #if defined Q_CC_GNU |
|
73 # include <w32api.h> |
|
74 #endif |
|
75 |
|
76 #ifndef Q_OS_WIN64 |
|
77 #define ULONG_PTR DWORD |
|
78 #endif |
|
79 |
|
80 QT_BEGIN_NAMESPACE |
|
81 |
|
82 extern HHOOK qax_hhook; |
|
83 |
|
84 // in qaxserver.cpp |
|
85 extern ITypeLib *qAxTypeLibrary; |
|
86 extern QAxFactory *qAxFactory(); |
|
87 extern unsigned long qAxLock(); |
|
88 extern unsigned long qAxUnlock(); |
|
89 extern HANDLE qAxInstance; |
|
90 extern bool qAxOutProcServer; |
|
91 |
|
92 static int invokeCount = 0; |
|
93 |
|
94 #ifdef QT_DEBUG |
|
95 unsigned long qaxserverbase_instance_count = 0; |
|
96 #endif |
|
97 |
|
98 // in qaxserverdll.cpp |
|
99 extern bool qax_ownQApp; |
|
100 |
|
101 struct QAxExceptInfo |
|
102 { |
|
103 QAxExceptInfo(int c, const QString &s, const QString &d, const QString &x) |
|
104 : code(c), src(s), desc(d), context(x) |
|
105 { |
|
106 } |
|
107 int code; |
|
108 QString src; |
|
109 QString desc; |
|
110 QString context; |
|
111 }; |
|
112 |
|
113 |
|
114 bool qt_sendSpontaneousEvent(QObject*, QEvent*); |
|
115 |
|
116 /* |
|
117 \class QAxServerBase |
|
118 \brief The QAxServerBase class is an ActiveX control hosting a QWidget. |
|
119 |
|
120 \internal |
|
121 */ |
|
122 class QAxServerBase : |
|
123 public QObject, |
|
124 public IAxServerBase, |
|
125 public IDispatch, |
|
126 public IOleObject, |
|
127 public IOleControl, |
|
128 #if defined Q_CC_GNU |
|
129 # if (__W32API_MAJOR_VERSION < 2 || (__W32API_MAJOR_VERSION == 2 && __W32API_MINOR_VERSION < 5)) |
|
130 public IViewObject, // this should not be needed as IViewObject2 is meant to inherit from this, |
|
131 // untill the mingw headers are fixed this will need to stay. |
|
132 # endif |
|
133 #endif |
|
134 public IViewObject2, |
|
135 public IOleInPlaceObject, |
|
136 public IOleInPlaceActiveObject, |
|
137 public IProvideClassInfo2, |
|
138 public IConnectionPointContainer, |
|
139 public IPersistStream, |
|
140 public IPersistStreamInit, |
|
141 public IPersistStorage, |
|
142 public IPersistPropertyBag, |
|
143 public IPersistFile, |
|
144 public IDataObject |
|
145 { |
|
146 public: |
|
147 typedef QMap<QUuid,IConnectionPoint*> ConnectionPoints; |
|
148 typedef QMap<QUuid,IConnectionPoint*>::Iterator ConnectionPointsIterator; |
|
149 |
|
150 QAxServerBase(const QString &classname, IUnknown *outerUnknown); |
|
151 QAxServerBase(QObject *o); |
|
152 |
|
153 void init(); |
|
154 |
|
155 ~QAxServerBase(); |
|
156 |
|
157 // Window creation |
|
158 HWND create(HWND hWndParent, RECT& rcPos); |
|
159 HMENU createPopup(QMenu *popup, HMENU oldMenu = 0); |
|
160 void createMenu(QMenuBar *menuBar); |
|
161 void removeMenu(); |
|
162 |
|
163 static LRESULT CALLBACK ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); |
|
164 |
|
165 // Object registration with OLE |
|
166 void registerActiveObject(IUnknown *object); |
|
167 void revokeActiveObject(); |
|
168 |
|
169 // IUnknown |
|
170 unsigned long WINAPI AddRef() |
|
171 { |
|
172 if (m_outerUnknown) |
|
173 return m_outerUnknown->AddRef(); |
|
174 |
|
175 EnterCriticalSection(&refCountSection); |
|
176 unsigned long r = ++ref; |
|
177 LeaveCriticalSection(&refCountSection); |
|
178 |
|
179 return r; |
|
180 } |
|
181 unsigned long WINAPI Release() |
|
182 { |
|
183 if (m_outerUnknown) |
|
184 return m_outerUnknown->Release(); |
|
185 |
|
186 EnterCriticalSection(&refCountSection); |
|
187 unsigned long r = --ref; |
|
188 LeaveCriticalSection(&refCountSection); |
|
189 |
|
190 if (!r) { |
|
191 delete this; |
|
192 return 0; |
|
193 } |
|
194 return r; |
|
195 } |
|
196 HRESULT WINAPI QueryInterface(REFIID iid, void **iface); |
|
197 HRESULT InternalQueryInterface(REFIID iid, void **iface); |
|
198 |
|
199 // IAxServerBase |
|
200 IUnknown *clientSite() const |
|
201 { |
|
202 return m_spClientSite; |
|
203 } |
|
204 |
|
205 void emitPropertyChanged(const char*); |
|
206 bool emitRequestPropertyChange(const char*); |
|
207 QObject *qObject() const |
|
208 { |
|
209 return theObject; |
|
210 } |
|
211 void ensureMetaData(); |
|
212 bool isPropertyExposed(int index); |
|
213 |
|
214 void reportError(int code, const QString &src, const QString &desc, const QString &context) |
|
215 { |
|
216 if (exception) |
|
217 delete exception; |
|
218 exception = new QAxExceptInfo(code, src, desc, context); |
|
219 } |
|
220 |
|
221 // IDispatch |
|
222 STDMETHOD(GetTypeInfoCount)(UINT* pctinfo); |
|
223 STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo); |
|
224 STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid); |
|
225 STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, |
|
226 LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, |
|
227 EXCEPINFO* pexcepinfo, UINT* puArgErr); |
|
228 |
|
229 // IProvideClassInfo |
|
230 STDMETHOD(GetClassInfo)(ITypeInfo** pptinfo); |
|
231 |
|
232 // IProvideClassInfo2 |
|
233 STDMETHOD(GetGUID)(DWORD dwGuidKind, GUID* pGUID); |
|
234 |
|
235 // IOleObject |
|
236 STDMETHOD(Advise)(IAdviseSink* pAdvSink, DWORD* pdwConnection); |
|
237 STDMETHOD(Close)(DWORD dwSaveOption); |
|
238 STDMETHOD(DoVerb)(LONG iVerb, LPMSG lpmsg, IOleClientSite* pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lprcPosRect); |
|
239 STDMETHOD(EnumAdvise)(IEnumSTATDATA** ppenumAdvise); |
|
240 STDMETHOD(EnumVerbs)(IEnumOLEVERB** ppEnumOleVerb); |
|
241 STDMETHOD(GetClientSite)(IOleClientSite** ppClientSite); |
|
242 STDMETHOD(GetClipboardData)(DWORD dwReserved, IDataObject** ppDataObject); |
|
243 STDMETHOD(GetExtent)(DWORD dwDrawAspect, SIZEL* psizel); |
|
244 STDMETHOD(GetMiscStatus)(DWORD dwAspect, DWORD *pdwStatus); |
|
245 STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk); |
|
246 STDMETHOD(GetUserClassID)(CLSID* pClsid); |
|
247 STDMETHOD(GetUserType)(DWORD dwFormOfType, LPOLESTR *pszUserType); |
|
248 STDMETHOD(InitFromData)(IDataObject* pDataObject, BOOL fCreation, DWORD dwReserved); |
|
249 STDMETHOD(IsUpToDate)(); |
|
250 STDMETHOD(SetClientSite)(IOleClientSite* pClientSite); |
|
251 STDMETHOD(SetColorScheme)(LOGPALETTE* pLogPal); |
|
252 STDMETHOD(SetExtent)(DWORD dwDrawAspect, SIZEL* psizel); |
|
253 STDMETHOD(SetHostNames)(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj); |
|
254 STDMETHOD(SetMoniker)(DWORD dwWhichMoniker, IMoniker* ppmk); |
|
255 STDMETHOD(Unadvise)(DWORD dwConnection); |
|
256 STDMETHOD(Update)(); |
|
257 |
|
258 // IViewObject |
|
259 STDMETHOD(Draw)(DWORD dwAspect, LONG lIndex, void *pvAspect, DVTARGETDEVICE *ptd, |
|
260 HDC hicTargetDevice, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, |
|
261 BOOL(__stdcall*pfnContinue)(ULONG_PTR), ULONG_PTR dwContinue); |
|
262 STDMETHOD(GetColorSet)(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, |
|
263 HDC hicTargetDev, LOGPALETTE **ppColorSet); |
|
264 STDMETHOD(Freeze)(DWORD dwAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze); |
|
265 STDMETHOD(Unfreeze)(DWORD dwFreeze); |
|
266 STDMETHOD(SetAdvise)(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink); |
|
267 STDMETHOD(GetAdvise)(DWORD *aspects, DWORD *advf, IAdviseSink **pAdvSink); |
|
268 |
|
269 // IViewObject2 |
|
270 STDMETHOD(GetExtent)(DWORD dwAspect, LONG lindex, DVTARGETDEVICE *ptd, LPSIZEL lpsizel); |
|
271 |
|
272 // IOleControl |
|
273 STDMETHOD(FreezeEvents)(BOOL); |
|
274 STDMETHOD(GetControlInfo)(LPCONTROLINFO); |
|
275 STDMETHOD(OnAmbientPropertyChange)(DISPID); |
|
276 STDMETHOD(OnMnemonic)(LPMSG); |
|
277 |
|
278 // IOleWindow |
|
279 STDMETHOD(GetWindow)(HWND *pHwnd); |
|
280 STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode); |
|
281 |
|
282 // IOleInPlaceObject |
|
283 STDMETHOD(InPlaceDeactivate)(); |
|
284 STDMETHOD(UIDeactivate)(); |
|
285 STDMETHOD(SetObjectRects)(LPCRECT lprcPosRect, LPCRECT lprcClipRect); |
|
286 STDMETHOD(ReactivateAndUndo)(); |
|
287 |
|
288 // IOleInPlaceActiveObject |
|
289 STDMETHOD(TranslateAcceleratorW)(MSG *pMsg); |
|
290 STDMETHOD(TranslateAcceleratorA)(MSG *pMsg); |
|
291 STDMETHOD(OnFrameWindowActivate)(BOOL); |
|
292 STDMETHOD(OnDocWindowActivate)(BOOL fActivate); |
|
293 STDMETHOD(ResizeBorder)(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow); |
|
294 STDMETHOD(EnableModeless)(BOOL); |
|
295 |
|
296 // IConnectionPointContainer |
|
297 STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints**); |
|
298 STDMETHOD(FindConnectionPoint)(REFIID, IConnectionPoint**); |
|
299 |
|
300 // IPersist |
|
301 STDMETHOD(GetClassID)(GUID*clsid) |
|
302 { |
|
303 *clsid = qAxFactory()->classID(class_name); |
|
304 return S_OK; |
|
305 } |
|
306 |
|
307 // IPersistStreamInit |
|
308 STDMETHOD(InitNew)(VOID); |
|
309 STDMETHOD(IsDirty)(); |
|
310 STDMETHOD(Load)(IStream *pStm); |
|
311 STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty); |
|
312 STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize); |
|
313 |
|
314 // IPersistPropertyBag |
|
315 STDMETHOD(Load)(IPropertyBag *, IErrorLog *); |
|
316 STDMETHOD(Save)(IPropertyBag *, BOOL, BOOL); |
|
317 |
|
318 // IPersistStorage |
|
319 STDMETHOD(InitNew)(IStorage *pStg); |
|
320 STDMETHOD(Load)(IStorage *pStg); |
|
321 STDMETHOD(Save)(IStorage *pStg, BOOL fSameAsLoad); |
|
322 STDMETHOD(SaveCompleted)(IStorage *pStgNew); |
|
323 STDMETHOD(HandsOffStorage)(); |
|
324 |
|
325 // IPersistFile |
|
326 STDMETHOD(SaveCompleted)(LPCOLESTR fileName); |
|
327 STDMETHOD(GetCurFile)(LPOLESTR *currentFile); |
|
328 STDMETHOD(Load)(LPCOLESTR fileName, DWORD mode); |
|
329 STDMETHOD(Save)(LPCOLESTR fileName, BOOL fRemember); |
|
330 |
|
331 // IDataObject |
|
332 STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium); |
|
333 STDMETHOD(GetDataHere)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */); |
|
334 STDMETHOD(QueryGetData)(FORMATETC* /* pformatetc */); |
|
335 STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */); |
|
336 STDMETHOD(SetData)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */); |
|
337 STDMETHOD(EnumFormatEtc)(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */); |
|
338 STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection); |
|
339 STDMETHOD(DUnadvise)(DWORD dwConnection); |
|
340 STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise); |
|
341 |
|
342 // QObject |
|
343 int qt_metacall(QMetaObject::Call, int index, void **argv); |
|
344 |
|
345 bool eventFilter(QObject *o, QEvent *e); |
|
346 private: |
|
347 void update(); |
|
348 void resize(const QSize &newSize); |
|
349 void updateGeometry(); |
|
350 void updateMask(); |
|
351 bool internalCreate(); |
|
352 void internalBind(); |
|
353 void internalConnect(); |
|
354 HRESULT internalActivate(); |
|
355 |
|
356 friend class QAxBindable; |
|
357 friend class QAxPropertyPage; |
|
358 |
|
359 QAxAggregated *aggregatedObject; |
|
360 ConnectionPoints points; |
|
361 |
|
362 union { |
|
363 QWidget *widget; |
|
364 QObject *object; |
|
365 } qt; |
|
366 QPointer<QObject> theObject; |
|
367 unsigned isWidget :1; |
|
368 unsigned ownObject :1; |
|
369 unsigned initNewCalled :1; |
|
370 unsigned dirtyflag :1; |
|
371 unsigned hasStockEvents :1; |
|
372 unsigned stayTopLevel :1; |
|
373 unsigned isInPlaceActive :1; |
|
374 unsigned isUIActive :1; |
|
375 unsigned wasUIActive :1; |
|
376 unsigned inDesignMode :1; |
|
377 unsigned canTakeFocus :1; |
|
378 short freezeEvents; |
|
379 |
|
380 HWND m_hWnd; |
|
381 |
|
382 HMENU hmenuShared; |
|
383 HOLEMENU holemenu; |
|
384 HWND hwndMenuOwner; |
|
385 QMap<HMENU, QMenu*> menuMap; |
|
386 QMap<UINT, QAction*> actionMap; |
|
387 QPointer<QMenuBar> menuBar; |
|
388 QPointer<QStatusBar> statusBar; |
|
389 QPointer<QMenu> currentPopup; |
|
390 QAxExceptInfo *exception; |
|
391 |
|
392 CRITICAL_SECTION refCountSection; |
|
393 CRITICAL_SECTION createWindowSection; |
|
394 |
|
395 unsigned long ref; |
|
396 unsigned long ole_ref; |
|
397 |
|
398 QString class_name; |
|
399 QString currentFileName; |
|
400 |
|
401 QHash<long, int> indexCache; |
|
402 QHash<int,DISPID> signalCache; |
|
403 |
|
404 IUnknown *m_outerUnknown; |
|
405 IAdviseSink *m_spAdviseSink; |
|
406 QList<STATDATA> adviseSinks; |
|
407 IOleClientSite *m_spClientSite; |
|
408 IOleInPlaceSiteWindowless *m_spInPlaceSite; |
|
409 IOleInPlaceFrame *m_spInPlaceFrame; |
|
410 ITypeInfo *m_spTypeInfo; |
|
411 IStorage *m_spStorage; |
|
412 QSize m_currentExtent; |
|
413 }; |
|
414 |
|
415 class QAxServerAggregate : public IUnknown |
|
416 { |
|
417 public: |
|
418 QAxServerAggregate(const QString &className, IUnknown *outerUnknown) |
|
419 : m_outerUnknown(outerUnknown), ref(0) |
|
420 { |
|
421 object = new QAxServerBase(className, outerUnknown); |
|
422 object->registerActiveObject(this); |
|
423 |
|
424 InitializeCriticalSection(&refCountSection); |
|
425 InitializeCriticalSection(&createWindowSection); |
|
426 } |
|
427 ~QAxServerAggregate() |
|
428 { |
|
429 DeleteCriticalSection(&refCountSection); |
|
430 DeleteCriticalSection(&createWindowSection); |
|
431 |
|
432 delete object; |
|
433 } |
|
434 |
|
435 // IUnknown |
|
436 unsigned long WINAPI AddRef() |
|
437 { |
|
438 EnterCriticalSection(&refCountSection); |
|
439 unsigned long r = ++ref; |
|
440 LeaveCriticalSection(&refCountSection); |
|
441 |
|
442 return r; |
|
443 } |
|
444 unsigned long WINAPI Release() |
|
445 { |
|
446 EnterCriticalSection(&refCountSection); |
|
447 unsigned long r = --ref; |
|
448 LeaveCriticalSection(&refCountSection); |
|
449 |
|
450 if (!r) { |
|
451 delete this; |
|
452 return 0; |
|
453 } |
|
454 return r; |
|
455 } |
|
456 HRESULT WINAPI QueryInterface(REFIID iid, void **iface) |
|
457 { |
|
458 *iface = 0; |
|
459 |
|
460 HRESULT res = E_NOINTERFACE; |
|
461 if (iid == IID_IUnknown) { |
|
462 *iface = (IUnknown*)this; |
|
463 AddRef(); |
|
464 return S_OK; |
|
465 } |
|
466 return object->InternalQueryInterface(iid, iface); |
|
467 } |
|
468 |
|
469 private: |
|
470 QAxServerBase *object; |
|
471 IUnknown *m_outerUnknown; |
|
472 unsigned long ref; |
|
473 |
|
474 CRITICAL_SECTION refCountSection; |
|
475 CRITICAL_SECTION createWindowSection; |
|
476 }; |
|
477 |
|
478 bool QAxFactory::createObjectWrapper(QObject *object, IDispatch **wrapper) |
|
479 { |
|
480 *wrapper = 0; |
|
481 QAxServerBase *obj = new QAxServerBase(object); |
|
482 obj->QueryInterface(IID_IDispatch, (void**)wrapper); |
|
483 if (*wrapper) |
|
484 return true; |
|
485 |
|
486 delete obj; |
|
487 return false; |
|
488 } |
|
489 |
|
490 |
|
491 /* |
|
492 Helper class to enumerate all supported event interfaces. |
|
493 */ |
|
494 class QAxSignalVec : public IEnumConnectionPoints |
|
495 { |
|
496 public: |
|
497 QAxSignalVec(const QAxServerBase::ConnectionPoints &points) |
|
498 : cpoints(points), ref(0) |
|
499 { |
|
500 InitializeCriticalSection(&refCountSection); |
|
501 for (QAxServerBase::ConnectionPointsIterator i = cpoints.begin(); i != cpoints.end(); ++i) |
|
502 (*i)->AddRef(); |
|
503 } |
|
504 QAxSignalVec(const QAxSignalVec &old) |
|
505 { |
|
506 InitializeCriticalSection(&refCountSection); |
|
507 ref = 0; |
|
508 cpoints = old.cpoints; |
|
509 for (QAxServerBase::ConnectionPointsIterator i = cpoints.begin(); i != cpoints.end(); ++i) |
|
510 (*i)->AddRef(); |
|
511 it = old.it; |
|
512 } |
|
513 ~QAxSignalVec() |
|
514 { |
|
515 for (QAxServerBase::ConnectionPointsIterator i = cpoints.begin(); i != cpoints.end(); ++i) |
|
516 (*i)->Release(); |
|
517 |
|
518 DeleteCriticalSection(&refCountSection); |
|
519 } |
|
520 |
|
521 unsigned long __stdcall AddRef() |
|
522 { |
|
523 EnterCriticalSection(&refCountSection); |
|
524 unsigned long r = ++ref; |
|
525 LeaveCriticalSection(&refCountSection); |
|
526 return ++r; |
|
527 } |
|
528 unsigned long __stdcall Release() |
|
529 { |
|
530 EnterCriticalSection(&refCountSection); |
|
531 unsigned long r = --ref; |
|
532 LeaveCriticalSection(&refCountSection); |
|
533 |
|
534 if (!r) { |
|
535 delete this; |
|
536 return 0; |
|
537 } |
|
538 return r; |
|
539 } |
|
540 STDMETHOD(QueryInterface)(REFIID iid, void **iface) |
|
541 { |
|
542 *iface = 0; |
|
543 if (iid == IID_IUnknown) |
|
544 *iface = this; |
|
545 else if (iid == IID_IEnumConnectionPoints) |
|
546 *iface = this; |
|
547 else |
|
548 return E_NOINTERFACE; |
|
549 |
|
550 AddRef(); |
|
551 return S_OK; |
|
552 } |
|
553 STDMETHOD(Next)(ULONG cConnections, IConnectionPoint **cpoint, ULONG *pcFetched) |
|
554 { |
|
555 unsigned long i; |
|
556 for (i = 0; i < cConnections; i++) { |
|
557 if (it == cpoints.end()) |
|
558 break; |
|
559 IConnectionPoint *cp = *it; |
|
560 cp->AddRef(); |
|
561 cpoint[i] = cp; |
|
562 ++it; |
|
563 } |
|
564 *pcFetched = i; |
|
565 return i == cConnections ? S_OK : S_FALSE; |
|
566 } |
|
567 STDMETHOD(Skip)(ULONG cConnections) |
|
568 { |
|
569 while (cConnections) { |
|
570 ++it; |
|
571 --cConnections; |
|
572 if (it == cpoints.end()) |
|
573 return S_FALSE; |
|
574 } |
|
575 return S_OK; |
|
576 } |
|
577 STDMETHOD(Reset)() |
|
578 { |
|
579 it = cpoints.begin(); |
|
580 |
|
581 return S_OK; |
|
582 } |
|
583 STDMETHOD(Clone)(IEnumConnectionPoints **ppEnum) |
|
584 { |
|
585 *ppEnum = new QAxSignalVec(*this); |
|
586 (*ppEnum)->AddRef(); |
|
587 |
|
588 return S_OK; |
|
589 } |
|
590 |
|
591 QAxServerBase::ConnectionPoints cpoints; |
|
592 QAxServerBase::ConnectionPointsIterator it; |
|
593 |
|
594 private: |
|
595 CRITICAL_SECTION refCountSection; |
|
596 |
|
597 unsigned long ref; |
|
598 }; |
|
599 |
|
600 /* |
|
601 Helper class to store and enumerate all connected event listeners. |
|
602 */ |
|
603 class QAxConnection : public IConnectionPoint, |
|
604 public IEnumConnections |
|
605 { |
|
606 public: |
|
607 typedef QList<CONNECTDATA> Connections; |
|
608 typedef QList<CONNECTDATA>::Iterator Iterator; |
|
609 |
|
610 QAxConnection(QAxServerBase *parent, const QUuid &uuid) |
|
611 : that(parent), iid(uuid), ref(1) |
|
612 { |
|
613 InitializeCriticalSection(&refCountSection); |
|
614 } |
|
615 QAxConnection(const QAxConnection &old) |
|
616 { |
|
617 InitializeCriticalSection(&refCountSection); |
|
618 ref = 0; |
|
619 connections = old.connections; |
|
620 it = old.it; |
|
621 that = old.that; |
|
622 iid = old.iid; |
|
623 QList<CONNECTDATA>::Iterator it = connections.begin(); |
|
624 while (it != connections.end()) { |
|
625 CONNECTDATA connection = *it; |
|
626 ++it; |
|
627 connection.pUnk->AddRef(); |
|
628 } |
|
629 } |
|
630 ~QAxConnection() |
|
631 { |
|
632 DeleteCriticalSection(&refCountSection); |
|
633 } |
|
634 |
|
635 unsigned long __stdcall AddRef() |
|
636 { |
|
637 EnterCriticalSection(&refCountSection); |
|
638 unsigned long r = ++ref; |
|
639 LeaveCriticalSection(&refCountSection); |
|
640 return r; |
|
641 } |
|
642 unsigned long __stdcall Release() |
|
643 { |
|
644 EnterCriticalSection(&refCountSection); |
|
645 unsigned long r = --ref; |
|
646 LeaveCriticalSection(&refCountSection); |
|
647 |
|
648 if (!r) { |
|
649 delete this; |
|
650 return 0; |
|
651 } |
|
652 return r; |
|
653 } |
|
654 STDMETHOD(QueryInterface)(REFIID iid, void **iface) |
|
655 { |
|
656 *iface = 0; |
|
657 if (iid == IID_IUnknown) |
|
658 *iface = (IConnectionPoint*)this; |
|
659 else if (iid == IID_IConnectionPoint) |
|
660 *iface = this; |
|
661 else if (iid == IID_IEnumConnections) |
|
662 *iface = this; |
|
663 else |
|
664 return E_NOINTERFACE; |
|
665 |
|
666 AddRef(); |
|
667 return S_OK; |
|
668 } |
|
669 STDMETHOD(GetConnectionInterface)(IID *pIID) |
|
670 { |
|
671 *pIID = iid; |
|
672 return S_OK; |
|
673 } |
|
674 STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer **ppCPC) |
|
675 { |
|
676 return that->QueryInterface(IID_IConnectionPointContainer, (void**)ppCPC); |
|
677 } |
|
678 STDMETHOD(Advise)(IUnknown*pUnk, DWORD *pdwCookie) |
|
679 { |
|
680 { |
|
681 IDispatch *checkImpl = 0; |
|
682 pUnk->QueryInterface(iid, (void**)&checkImpl); |
|
683 if (!checkImpl) |
|
684 return CONNECT_E_CANNOTCONNECT; |
|
685 checkImpl->Release(); |
|
686 } |
|
687 |
|
688 CONNECTDATA cd; |
|
689 cd.dwCookie = connections.count()+1; |
|
690 cd.pUnk = pUnk; |
|
691 cd.pUnk->AddRef(); |
|
692 connections.append(cd); |
|
693 |
|
694 *pdwCookie = cd.dwCookie; |
|
695 return S_OK; |
|
696 } |
|
697 STDMETHOD(Unadvise)(DWORD dwCookie) |
|
698 { |
|
699 QList<CONNECTDATA>::Iterator it = connections.begin(); |
|
700 while (it != connections.end()) { |
|
701 CONNECTDATA cd = *it; |
|
702 if (cd.dwCookie == dwCookie) { |
|
703 cd.pUnk->Release(); |
|
704 connections.erase(it); |
|
705 return S_OK; |
|
706 } |
|
707 ++it; |
|
708 } |
|
709 return CONNECT_E_NOCONNECTION; |
|
710 } |
|
711 STDMETHOD(EnumConnections)(IEnumConnections **ppEnum) |
|
712 { |
|
713 *ppEnum = this; |
|
714 AddRef(); |
|
715 |
|
716 return S_OK; |
|
717 } |
|
718 STDMETHOD(Next)(ULONG cConnections, CONNECTDATA *cd, ULONG *pcFetched) |
|
719 { |
|
720 unsigned long i; |
|
721 for (i = 0; i < cConnections; i++) { |
|
722 if (it == connections.end()) |
|
723 break; |
|
724 cd[i] = *it; |
|
725 cd[i].pUnk->AddRef(); |
|
726 ++it; |
|
727 } |
|
728 if (pcFetched) |
|
729 *pcFetched = i; |
|
730 return i == cConnections ? S_OK : S_FALSE; |
|
731 } |
|
732 STDMETHOD(Skip)(ULONG cConnections) |
|
733 { |
|
734 while (cConnections) { |
|
735 ++it; |
|
736 --cConnections; |
|
737 if (it == connections.end()) |
|
738 return S_FALSE; |
|
739 } |
|
740 return S_OK; |
|
741 } |
|
742 STDMETHOD(Reset)() |
|
743 { |
|
744 it = connections.begin(); |
|
745 |
|
746 return S_OK; |
|
747 } |
|
748 STDMETHOD(Clone)(IEnumConnections **ppEnum) |
|
749 { |
|
750 *ppEnum = new QAxConnection(*this); |
|
751 (*ppEnum)->AddRef(); |
|
752 |
|
753 return S_OK; |
|
754 } |
|
755 |
|
756 private: |
|
757 QAxServerBase *that; |
|
758 QUuid iid; |
|
759 Connections connections; |
|
760 Iterator it; |
|
761 |
|
762 CRITICAL_SECTION refCountSection; |
|
763 unsigned long ref; |
|
764 }; |
|
765 |
|
766 // callback for DLL server to hook into non-Qt eventloop |
|
767 LRESULT CALLBACK axs_FilterProc(int nCode, WPARAM wParam, LPARAM lParam) |
|
768 { |
|
769 if (qApp && !invokeCount) |
|
770 qApp->sendPostedEvents(); |
|
771 |
|
772 return CallNextHookEx(qax_hhook, nCode, wParam, lParam); |
|
773 } |
|
774 |
|
775 // filter for executable case to hook into Qt eventloop |
|
776 // for DLLs the client calls TranslateAccelerator |
|
777 bool qax_winEventFilter(void *message) |
|
778 { |
|
779 MSG *pMsg = (MSG*)message; |
|
780 if (pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) |
|
781 return false; |
|
782 |
|
783 bool ret = false; |
|
784 QWidget *aqt = QWidget::find(pMsg->hwnd); |
|
785 if (!aqt) |
|
786 return ret; |
|
787 |
|
788 HWND baseHwnd = ::GetParent(aqt->winId()); |
|
789 QAxServerBase *axbase = 0; |
|
790 while (!axbase && baseHwnd) { |
|
791 #ifdef GWLP_USERDATA |
|
792 axbase = (QAxServerBase*)GetWindowLongPtr(baseHwnd, GWLP_USERDATA); |
|
793 #else |
|
794 axbase = (QAxServerBase*)GetWindowLong(baseHwnd, GWL_USERDATA); |
|
795 #endif |
|
796 |
|
797 baseHwnd = ::GetParent(baseHwnd); |
|
798 } |
|
799 if (!axbase) |
|
800 return ret; |
|
801 |
|
802 HRESULT hres = axbase->TranslateAcceleratorW(pMsg); |
|
803 return hres == S_OK; |
|
804 } |
|
805 |
|
806 extern void qWinMsgHandler(QtMsgType t, const char* str); |
|
807 |
|
808 // COM Factory class, mapping COM requests to ActiveQt requests. |
|
809 // One instance of this class for each ActiveX the server can provide. |
|
810 class QClassFactory : public IClassFactory2 |
|
811 { |
|
812 public: |
|
813 QClassFactory(CLSID clsid) |
|
814 : ref(0), licensed(false) |
|
815 { |
|
816 InitializeCriticalSection(&refCountSection); |
|
817 |
|
818 // COM only knows the CLSID, but QAxFactory is class name based... |
|
819 QStringList keys = qAxFactory()->featureList(); |
|
820 for (QStringList::Iterator key = keys.begin(); key != keys.end(); ++key) { |
|
821 if (qAxFactory()->classID(*key) == clsid) { |
|
822 className = *key; |
|
823 break; |
|
824 } |
|
825 } |
|
826 |
|
827 const QMetaObject *mo = qAxFactory()->metaObject(className); |
|
828 if (mo) { |
|
829 classKey = QLatin1String(mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value()); |
|
830 licensed = !classKey.isEmpty(); |
|
831 } |
|
832 } |
|
833 |
|
834 ~QClassFactory() |
|
835 { |
|
836 DeleteCriticalSection(&refCountSection); |
|
837 } |
|
838 |
|
839 // IUnknown |
|
840 unsigned long WINAPI AddRef() |
|
841 { |
|
842 EnterCriticalSection(&refCountSection); |
|
843 unsigned long r = ++ref; |
|
844 LeaveCriticalSection(&refCountSection); |
|
845 return ++r; |
|
846 } |
|
847 unsigned long WINAPI Release() |
|
848 { |
|
849 EnterCriticalSection(&refCountSection); |
|
850 unsigned long r = --ref; |
|
851 LeaveCriticalSection(&refCountSection); |
|
852 |
|
853 if (!r) { |
|
854 delete this; |
|
855 return 0; |
|
856 } |
|
857 return r; |
|
858 } |
|
859 HRESULT WINAPI QueryInterface(REFIID iid, LPVOID *iface) |
|
860 { |
|
861 *iface = 0; |
|
862 if (iid == IID_IUnknown) |
|
863 *iface = (IUnknown*)this; |
|
864 else if (iid == IID_IClassFactory) |
|
865 *iface = (IClassFactory*)this; |
|
866 else if (iid == IID_IClassFactory2 && licensed) |
|
867 *iface = (IClassFactory2*)this; |
|
868 else |
|
869 return E_NOINTERFACE; |
|
870 |
|
871 AddRef(); |
|
872 return S_OK; |
|
873 } |
|
874 |
|
875 HRESULT WINAPI CreateInstanceHelper(IUnknown *pUnkOuter, REFIID iid, void **ppObject) |
|
876 { |
|
877 if (pUnkOuter) { |
|
878 if (iid != IID_IUnknown) |
|
879 return CLASS_E_NOAGGREGATION; |
|
880 const QMetaObject *mo = qAxFactory()->metaObject(className); |
|
881 if (mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Aggregatable")).value(), "no")) |
|
882 return CLASS_E_NOAGGREGATION; |
|
883 } |
|
884 |
|
885 // Make sure a QApplication instance is present (inprocess case) |
|
886 if (!qApp) { |
|
887 qInstallMsgHandler(qWinMsgHandler); |
|
888 qax_ownQApp = true; |
|
889 int argc = 0; |
|
890 QApplication *app = new QApplication(argc, 0); |
|
891 } |
|
892 qApp->setQuitOnLastWindowClosed(false); |
|
893 |
|
894 if (qAxOutProcServer) |
|
895 QAbstractEventDispatcher::instance()->setEventFilter(qax_winEventFilter); |
|
896 else |
|
897 QApplication::instance()->d_func()->in_exec = true; |
|
898 |
|
899 // hook into eventloop; this allows a server to create his own QApplication object |
|
900 if (!qax_hhook && qax_ownQApp) { |
|
901 qax_hhook = SetWindowsHookEx(WH_GETMESSAGE, axs_FilterProc, 0, GetCurrentThreadId()); |
|
902 } |
|
903 |
|
904 HRESULT res; |
|
905 // Create the ActiveX wrapper - aggregate if requested |
|
906 if (pUnkOuter) { |
|
907 QAxServerAggregate *aggregate = new QAxServerAggregate(className, pUnkOuter); |
|
908 res = aggregate->QueryInterface(iid, ppObject); |
|
909 if (FAILED(res)) |
|
910 delete aggregate; |
|
911 } else { |
|
912 QAxServerBase *activeqt = new QAxServerBase(className, pUnkOuter); |
|
913 res = activeqt->QueryInterface(iid, ppObject); |
|
914 if (FAILED(res)) |
|
915 delete activeqt; |
|
916 else |
|
917 activeqt->registerActiveObject((IUnknown*)(IDispatch*)activeqt); |
|
918 } |
|
919 return res; |
|
920 } |
|
921 |
|
922 // IClassFactory |
|
923 HRESULT WINAPI CreateInstance(IUnknown *pUnkOuter, REFIID iid, void **ppObject) |
|
924 { |
|
925 // class is licensed |
|
926 if (licensed && !qAxFactory()->validateLicenseKey(className, QString())) |
|
927 return CLASS_E_NOTLICENSED; |
|
928 |
|
929 return CreateInstanceHelper(pUnkOuter, iid, ppObject); |
|
930 } |
|
931 HRESULT WINAPI LockServer(BOOL fLock) |
|
932 { |
|
933 if (fLock) |
|
934 qAxLock(); |
|
935 else |
|
936 qAxUnlock(); |
|
937 |
|
938 return S_OK; |
|
939 } |
|
940 |
|
941 // IClassFactory2 |
|
942 HRESULT WINAPI RequestLicKey(DWORD, BSTR *pKey) |
|
943 { |
|
944 if (!pKey) |
|
945 return E_POINTER; |
|
946 *pKey = 0; |
|
947 |
|
948 // This of course works only on fully licensed machines |
|
949 if (!qAxFactory()->validateLicenseKey(className, QString())) |
|
950 return CLASS_E_NOTLICENSED; |
|
951 |
|
952 *pKey = QStringToBSTR(classKey); |
|
953 return S_OK; |
|
954 } |
|
955 |
|
956 HRESULT WINAPI GetLicInfo(LICINFO *pLicInfo) |
|
957 { |
|
958 if (!pLicInfo) |
|
959 return E_POINTER; |
|
960 pLicInfo->cbLicInfo = sizeof(LICINFO); |
|
961 |
|
962 // class specific license key? |
|
963 const QMetaObject *mo = qAxFactory()->metaObject(className); |
|
964 const char *key = mo->classInfo(mo->indexOfClassInfo("LicenseKey")).value(); |
|
965 pLicInfo->fRuntimeKeyAvail = key && key[0]; |
|
966 |
|
967 // machine fully licensed? |
|
968 pLicInfo->fLicVerified = qAxFactory()->validateLicenseKey(className, QString()); |
|
969 |
|
970 return S_OK; |
|
971 } |
|
972 |
|
973 HRESULT WINAPI CreateInstanceLic(IUnknown *pUnkOuter, IUnknown *pUnkReserved, REFIID iid, BSTR bKey, PVOID *ppObject) |
|
974 { |
|
975 QString licenseKey = QString::fromWCharArray(bKey); |
|
976 if (!qAxFactory()->validateLicenseKey(className, licenseKey)) |
|
977 return CLASS_E_NOTLICENSED; |
|
978 return CreateInstanceHelper(pUnkOuter, iid, ppObject); |
|
979 } |
|
980 |
|
981 QString className; |
|
982 |
|
983 protected: |
|
984 CRITICAL_SECTION refCountSection; |
|
985 unsigned long ref; |
|
986 bool licensed; |
|
987 QString classKey; |
|
988 }; |
|
989 |
|
990 // Create a QClassFactory object for class \a iid |
|
991 HRESULT GetClassObject(REFIID clsid, REFIID iid, void **ppUnk) |
|
992 { |
|
993 QClassFactory *factory = new QClassFactory(clsid); |
|
994 if (!factory) |
|
995 return E_OUTOFMEMORY; |
|
996 if (factory->className.isEmpty()) { |
|
997 delete factory; |
|
998 return E_NOINTERFACE; |
|
999 } |
|
1000 HRESULT res = factory->QueryInterface(iid, ppUnk); |
|
1001 if (res != S_OK) |
|
1002 delete factory; |
|
1003 return res; |
|
1004 } |
|
1005 |
|
1006 |
|
1007 /*! |
|
1008 Constructs a QAxServerBase object wrapping the QWidget \a |
|
1009 classname into an ActiveX control. |
|
1010 |
|
1011 The constructor is called by the QClassFactory object provided by |
|
1012 the COM server for the respective CLSID. |
|
1013 */ |
|
1014 QAxServerBase::QAxServerBase(const QString &classname, IUnknown *outerUnknown) |
|
1015 : aggregatedObject(0), ref(0), ole_ref(0), class_name(classname), |
|
1016 m_hWnd(0), hmenuShared(0), hwndMenuOwner(0), |
|
1017 m_outerUnknown(outerUnknown) |
|
1018 { |
|
1019 init(); |
|
1020 |
|
1021 internalCreate(); |
|
1022 } |
|
1023 |
|
1024 /*! |
|
1025 Constructs a QAxServerBase object wrapping \a o. |
|
1026 */ |
|
1027 QAxServerBase::QAxServerBase(QObject *o) |
|
1028 : aggregatedObject(0), ref(0), ole_ref(0), |
|
1029 m_hWnd(0), hmenuShared(0), hwndMenuOwner(0), |
|
1030 m_outerUnknown(0) |
|
1031 { |
|
1032 init(); |
|
1033 |
|
1034 qt.object = o; |
|
1035 if (o) { |
|
1036 theObject = o; |
|
1037 isWidget = false; |
|
1038 class_name = QLatin1String(o->metaObject()->className()); |
|
1039 } |
|
1040 internalBind(); |
|
1041 internalConnect(); |
|
1042 } |
|
1043 |
|
1044 /*! |
|
1045 Initializes data members. |
|
1046 */ |
|
1047 void QAxServerBase::init() |
|
1048 { |
|
1049 qt.object = 0; |
|
1050 isWidget = false; |
|
1051 ownObject = false; |
|
1052 initNewCalled = false; |
|
1053 dirtyflag = false; |
|
1054 hasStockEvents = false; |
|
1055 stayTopLevel = false; |
|
1056 isInPlaceActive = false; |
|
1057 isUIActive = false; |
|
1058 wasUIActive = false; |
|
1059 inDesignMode = false; |
|
1060 canTakeFocus = false; |
|
1061 freezeEvents = 0; |
|
1062 exception = 0; |
|
1063 |
|
1064 m_spAdviseSink = 0; |
|
1065 m_spClientSite = 0; |
|
1066 m_spInPlaceSite = 0; |
|
1067 m_spInPlaceFrame = 0; |
|
1068 m_spTypeInfo = 0; |
|
1069 m_spStorage = 0; |
|
1070 |
|
1071 InitializeCriticalSection(&refCountSection); |
|
1072 InitializeCriticalSection(&createWindowSection); |
|
1073 |
|
1074 #ifdef QT_DEBUG |
|
1075 EnterCriticalSection(&refCountSection); |
|
1076 ++qaxserverbase_instance_count; |
|
1077 LeaveCriticalSection(&refCountSection); |
|
1078 #endif |
|
1079 |
|
1080 qAxLock(); |
|
1081 |
|
1082 points[IID_IPropertyNotifySink] = new QAxConnection(this, IID_IPropertyNotifySink); |
|
1083 } |
|
1084 |
|
1085 /*! |
|
1086 Destroys the QAxServerBase object, releasing all allocated |
|
1087 resources and interfaces. |
|
1088 */ |
|
1089 QAxServerBase::~QAxServerBase() |
|
1090 { |
|
1091 #ifdef QT_DEBUG |
|
1092 EnterCriticalSection(&refCountSection); |
|
1093 --qaxserverbase_instance_count; |
|
1094 LeaveCriticalSection(&refCountSection); |
|
1095 #endif |
|
1096 |
|
1097 revokeActiveObject(); |
|
1098 |
|
1099 for (QAxServerBase::ConnectionPointsIterator it = points.begin(); it != points.end(); ++it) { |
|
1100 if (it.value()) |
|
1101 (*it)->Release(); |
|
1102 } |
|
1103 delete aggregatedObject; |
|
1104 aggregatedObject = 0; |
|
1105 if (theObject) { |
|
1106 qt.object->disconnect(this); |
|
1107 QObject *aqt = qt.object; |
|
1108 qt.object = 0; |
|
1109 if (ownObject) |
|
1110 delete aqt; |
|
1111 } |
|
1112 |
|
1113 if (m_spAdviseSink) m_spAdviseSink->Release(); |
|
1114 m_spAdviseSink = 0; |
|
1115 for (int i = 0; i < adviseSinks.count(); ++i) { |
|
1116 adviseSinks.at(i).pAdvSink->Release(); |
|
1117 } |
|
1118 if (m_spClientSite) m_spClientSite->Release(); |
|
1119 m_spClientSite = 0; |
|
1120 if (m_spInPlaceFrame) m_spInPlaceFrame->Release(); |
|
1121 m_spInPlaceFrame = 0; |
|
1122 if (m_spInPlaceSite) m_spInPlaceSite->Release(); |
|
1123 m_spInPlaceSite = 0; |
|
1124 if (m_spTypeInfo) m_spTypeInfo->Release(); |
|
1125 m_spTypeInfo = 0; |
|
1126 if (m_spStorage) m_spStorage->Release(); |
|
1127 m_spStorage = 0; |
|
1128 |
|
1129 DeleteCriticalSection(&refCountSection); |
|
1130 DeleteCriticalSection(&createWindowSection); |
|
1131 |
|
1132 qAxUnlock(); |
|
1133 } |
|
1134 |
|
1135 /* |
|
1136 Registering with OLE |
|
1137 */ |
|
1138 void QAxServerBase::registerActiveObject(IUnknown *object) |
|
1139 { |
|
1140 if (ole_ref || !qt.object || !qAxOutProcServer) |
|
1141 return; |
|
1142 |
|
1143 const QMetaObject *mo = qt.object->metaObject(); |
|
1144 if (!qstricmp(mo->classInfo(mo->indexOfClassInfo("RegisterObject")).value(), "yes")) |
|
1145 RegisterActiveObject(object, qAxFactory()->classID(class_name), ACTIVEOBJECT_WEAK, &ole_ref); |
|
1146 } |
|
1147 |
|
1148 void QAxServerBase::revokeActiveObject() |
|
1149 { |
|
1150 if (!ole_ref) |
|
1151 return; |
|
1152 |
|
1153 RevokeActiveObject(ole_ref, 0); |
|
1154 ole_ref = 0; |
|
1155 } |
|
1156 |
|
1157 /* |
|
1158 QueryInterface implementation. |
|
1159 */ |
|
1160 HRESULT WINAPI QAxServerBase::QueryInterface(REFIID iid, void **iface) |
|
1161 { |
|
1162 if (m_outerUnknown) |
|
1163 return m_outerUnknown->QueryInterface(iid, iface); |
|
1164 |
|
1165 return InternalQueryInterface(iid, iface); |
|
1166 } |
|
1167 |
|
1168 HRESULT QAxServerBase::InternalQueryInterface(REFIID iid, void **iface) |
|
1169 { |
|
1170 *iface = 0; |
|
1171 |
|
1172 if (iid == IID_IUnknown) { |
|
1173 *iface = (IUnknown*)(IDispatch*)this; |
|
1174 } else { |
|
1175 HRESULT res = S_OK; |
|
1176 if (aggregatedObject) |
|
1177 res = aggregatedObject->queryInterface(iid, iface); |
|
1178 if (*iface) |
|
1179 return res; |
|
1180 } |
|
1181 |
|
1182 if (!(*iface)) { |
|
1183 if (iid == qAxFactory()->interfaceID(class_name)) |
|
1184 *iface = (IDispatch*)this; |
|
1185 if (iid == IID_IDispatch) |
|
1186 *iface = (IDispatch*)this; |
|
1187 else if (iid == IID_IAxServerBase) |
|
1188 *iface = (IAxServerBase*)this; |
|
1189 else if (iid == IID_IOleObject) |
|
1190 *iface = (IOleObject*)this; |
|
1191 else if (iid == IID_IConnectionPointContainer) |
|
1192 *iface = (IConnectionPointContainer*)this; |
|
1193 else if (iid == IID_IProvideClassInfo) |
|
1194 *iface = (IProvideClassInfo*)this; |
|
1195 else if (iid == IID_IProvideClassInfo2) |
|
1196 *iface = (IProvideClassInfo2*)this; |
|
1197 else if (iid == IID_IPersist) |
|
1198 *iface = (IPersist*)(IPersistStream*)this; |
|
1199 else if (iid == IID_IPersistStream) |
|
1200 *iface = (IPersistStream*)this; |
|
1201 else if (iid == IID_IPersistStreamInit) |
|
1202 *iface = (IPersistStreamInit*)this; |
|
1203 else if (iid == IID_IPersistStorage) |
|
1204 *iface = (IPersistStorage*)this; |
|
1205 else if (iid == IID_IPersistPropertyBag) |
|
1206 *iface = (IPersistPropertyBag*)this; |
|
1207 else if (iid == IID_IPersistFile && |
|
1208 qAxFactory()->metaObject(class_name)->indexOfClassInfo("MIME") != -1) |
|
1209 *iface = (IPersistFile*)this; |
|
1210 else if (iid == IID_IViewObject) |
|
1211 *iface = (IViewObject*)this; |
|
1212 else if (iid == IID_IViewObject2) |
|
1213 *iface = (IViewObject2*)this; |
|
1214 else if (isWidget) { |
|
1215 if (iid == IID_IOleControl) |
|
1216 *iface = (IOleControl*)this; |
|
1217 else if (iid == IID_IOleWindow) |
|
1218 *iface = (IOleWindow*)(IOleInPlaceObject*)this; |
|
1219 else if (iid == IID_IOleInPlaceObject) |
|
1220 *iface = (IOleInPlaceObject*)this; |
|
1221 else if (iid == IID_IOleInPlaceActiveObject) |
|
1222 *iface = (IOleInPlaceActiveObject*)this; |
|
1223 else if (iid == IID_IDataObject) |
|
1224 *iface = (IDataObject*)this; |
|
1225 } |
|
1226 } |
|
1227 if (!*iface) |
|
1228 return E_NOINTERFACE; |
|
1229 |
|
1230 AddRef(); |
|
1231 return S_OK; |
|
1232 } |
|
1233 |
|
1234 /*! |
|
1235 Detects and initilaizes implementation of QAxBindable in objects. |
|
1236 */ |
|
1237 void QAxServerBase::internalBind() |
|
1238 { |
|
1239 QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable"); |
|
1240 if (axb) { |
|
1241 // no addref; this is aggregated |
|
1242 axb->activex = this; |
|
1243 if (!aggregatedObject) |
|
1244 aggregatedObject = axb->createAggregate(); |
|
1245 if (aggregatedObject) { |
|
1246 aggregatedObject->controlling_unknown = (IUnknown*)(IDispatch*)this; |
|
1247 aggregatedObject->the_object = qt.object; |
|
1248 } |
|
1249 } |
|
1250 } |
|
1251 |
|
1252 /*! |
|
1253 Connects object signals to event dispatcher. |
|
1254 */ |
|
1255 void QAxServerBase::internalConnect() |
|
1256 { |
|
1257 QUuid eventsID = qAxFactory()->eventsID(class_name); |
|
1258 if (!eventsID.isNull()) { |
|
1259 if (!points[eventsID]) |
|
1260 points[eventsID] = new QAxConnection(this, eventsID); |
|
1261 |
|
1262 // connect the generic slot to all signals of qt.object |
|
1263 const QMetaObject *mo = qt.object->metaObject(); |
|
1264 for (int isignal = mo->methodCount()-1; isignal >= 0; --isignal) { |
|
1265 if (mo->method(isignal).methodType() == QMetaMethod::Signal) |
|
1266 QMetaObject::connect(qt.object, isignal, this, isignal); |
|
1267 } |
|
1268 } |
|
1269 } |
|
1270 |
|
1271 /*! |
|
1272 Creates the QWidget for the classname passed to the c'tor. |
|
1273 |
|
1274 All signals of the widget class are connected to the internal event mapper. |
|
1275 If the widget implements QAxBindable, stock events are also connected. |
|
1276 */ |
|
1277 bool QAxServerBase::internalCreate() |
|
1278 { |
|
1279 if (qt.object) |
|
1280 return true; |
|
1281 |
|
1282 qt.object = qAxFactory()->createObject(class_name); |
|
1283 Q_ASSERT(qt.object); |
|
1284 if (!qt.object) |
|
1285 return false; |
|
1286 |
|
1287 theObject = qt.object; |
|
1288 ownObject = true; |
|
1289 isWidget = qt.object->isWidgetType(); |
|
1290 hasStockEvents = qAxFactory()->hasStockEvents(class_name); |
|
1291 stayTopLevel = qAxFactory()->stayTopLevel(class_name); |
|
1292 |
|
1293 internalBind(); |
|
1294 if (isWidget) { |
|
1295 if (!stayTopLevel) { |
|
1296 QEvent e(QEvent::EmbeddingControl); |
|
1297 QApplication::sendEvent(qt.widget, &e); |
|
1298 ::SetWindowLong(qt.widget->winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); |
|
1299 } |
|
1300 qt.widget->setAttribute(Qt::WA_QuitOnClose, false); |
|
1301 qt.widget->move(0, 0); |
|
1302 |
|
1303 // initialize to sizeHint, but don't set resized flag so that container has a chance to override |
|
1304 bool wasResized = qt.widget->testAttribute(Qt::WA_Resized); |
|
1305 updateGeometry(); |
|
1306 if (!wasResized && qt.widget->testAttribute(Qt::WA_Resized) |
|
1307 && qt.widget->sizePolicy() != QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)) { |
|
1308 qt.widget->setAttribute(Qt::WA_Resized, false); |
|
1309 } |
|
1310 } |
|
1311 |
|
1312 internalConnect(); |
|
1313 // install an event filter for stock events |
|
1314 if (isWidget) { |
|
1315 qt.object->installEventFilter(this); |
|
1316 const QList<QWidget*> children = qFindChildren<QWidget*>(qt.object); |
|
1317 QList<QWidget*>::ConstIterator it = children.constBegin(); |
|
1318 while (it != children.constEnd()) { |
|
1319 (*it)->installEventFilter(this); |
|
1320 ++it; |
|
1321 } |
|
1322 } |
|
1323 return true; |
|
1324 } |
|
1325 |
|
1326 /* |
|
1327 class HackMenuData : public QMenuData |
|
1328 { |
|
1329 friend class QAxServerBase; |
|
1330 }; |
|
1331 */ |
|
1332 |
|
1333 class HackWidget : public QWidget |
|
1334 { |
|
1335 friend class QAxServerBase; |
|
1336 }; |
|
1337 /* |
|
1338 Message handler. \a hWnd is always the ActiveX widget hosting the Qt widget. |
|
1339 \a uMsg is handled as follows |
|
1340 \list |
|
1341 \i WM_CREATE The ActiveX control is created |
|
1342 \i WM_DESTROY The QWidget is destroyed |
|
1343 \i WM_SHOWWINDOW The QWidget is parented into the ActiveX window |
|
1344 \i WM_PAINT The QWidget is updated |
|
1345 \i WM_SIZE The QWidget is resized to the new size |
|
1346 \i WM_SETFOCUS and |
|
1347 \i WM_KILLFOCUS The client site is notified about the focus transfer |
|
1348 \i WM_MOUSEACTIVATE The ActiveX is activated |
|
1349 \endlist |
|
1350 |
|
1351 The semantics of \a wParam and \a lParam depend on the value of \a uMsg. |
|
1352 */ |
|
1353 LRESULT CALLBACK QAxServerBase::ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
|
1354 { |
|
1355 if (uMsg == WM_CREATE) { |
|
1356 CREATESTRUCT *cs = (CREATESTRUCT*)lParam; |
|
1357 QAxServerBase *that = (QAxServerBase*)cs->lpCreateParams; |
|
1358 |
|
1359 #ifdef GWLP_USERDATA |
|
1360 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)that); |
|
1361 #else |
|
1362 SetWindowLong(hWnd, GWL_USERDATA, (LONG)that); |
|
1363 #endif |
|
1364 |
|
1365 that->m_hWnd = hWnd; |
|
1366 |
|
1367 return ::DefWindowProc(hWnd, uMsg, wParam, lParam); |
|
1368 } |
|
1369 |
|
1370 QAxServerBase *that = 0; |
|
1371 |
|
1372 #ifdef GWLP_USERDATA |
|
1373 that = (QAxServerBase*)GetWindowLongPtr(hWnd, GWLP_USERDATA); |
|
1374 #else |
|
1375 that = (QAxServerBase*)GetWindowLong(hWnd, GWL_USERDATA); |
|
1376 #endif |
|
1377 |
|
1378 if (that) { |
|
1379 int width = that->qt.widget ? that->qt.widget->width() : 0; |
|
1380 int height = that->qt.widget ? that->qt.widget->height() : 0; |
|
1381 RECT rcPos = {0, 0, width + 1, height + 1}; |
|
1382 |
|
1383 switch (uMsg) { |
|
1384 case WM_NCDESTROY: |
|
1385 that->m_hWnd = 0; |
|
1386 break; |
|
1387 |
|
1388 case WM_QUERYENDSESSION: |
|
1389 case WM_DESTROY: |
|
1390 // save the window handle |
|
1391 if (that->qt.widget) { |
|
1392 that->qt.widget->hide(); |
|
1393 ::SetParent(that->qt.widget->winId(), 0); |
|
1394 } |
|
1395 break; |
|
1396 |
|
1397 case WM_SHOWWINDOW: |
|
1398 if(wParam) { |
|
1399 that->internalCreate(); |
|
1400 if (!that->stayTopLevel) { |
|
1401 ::SetParent(that->qt.widget->winId(), that->m_hWnd); |
|
1402 that->qt.widget->raise(); |
|
1403 that->qt.widget->move(0, 0); |
|
1404 } |
|
1405 that->qt.widget->show(); |
|
1406 } else if (that->qt.widget) { |
|
1407 that->qt.widget->hide(); |
|
1408 } |
|
1409 break; |
|
1410 |
|
1411 case WM_ERASEBKGND: |
|
1412 that->updateMask(); |
|
1413 break; |
|
1414 |
|
1415 case WM_SIZE: |
|
1416 that->resize(QSize(LOWORD(lParam), HIWORD(lParam))); |
|
1417 break; |
|
1418 |
|
1419 case WM_SETFOCUS: |
|
1420 if (that->isInPlaceActive && that->m_spClientSite && !that->inDesignMode && that->canTakeFocus) { |
|
1421 that->DoVerb(OLEIVERB_UIACTIVATE, NULL, that->m_spClientSite, 0, that->m_hWnd, &rcPos); |
|
1422 if (that->isUIActive) { |
|
1423 IOleControlSite *spSite = 0; |
|
1424 that->m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&spSite); |
|
1425 if (spSite) { |
|
1426 spSite->OnFocus(true); |
|
1427 spSite->Release(); |
|
1428 } |
|
1429 QWidget *candidate = that->qt.widget; |
|
1430 while (!(candidate->focusPolicy() & Qt::TabFocus)) { |
|
1431 candidate = candidate->nextInFocusChain(); |
|
1432 if (candidate == that->qt.widget) { |
|
1433 candidate = 0; |
|
1434 break; |
|
1435 } |
|
1436 } |
|
1437 if (candidate) { |
|
1438 candidate->setFocus(); |
|
1439 HackWidget *widget = (HackWidget*)that->qt.widget; |
|
1440 if (::GetKeyState(VK_SHIFT) < 0) |
|
1441 widget->focusNextPrevChild(false); |
|
1442 } |
|
1443 } |
|
1444 } |
|
1445 break; |
|
1446 |
|
1447 case WM_KILLFOCUS: |
|
1448 if (that->isInPlaceActive && that->isUIActive && that->m_spClientSite) { |
|
1449 IOleControlSite *spSite = 0; |
|
1450 that->m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&spSite); |
|
1451 if (spSite) { |
|
1452 if (!::IsChild(that->m_hWnd, ::GetFocus())) |
|
1453 spSite->OnFocus(false); |
|
1454 spSite->Release(); |
|
1455 } |
|
1456 } |
|
1457 break; |
|
1458 |
|
1459 case WM_MOUSEACTIVATE: |
|
1460 that->DoVerb(OLEIVERB_UIACTIVATE, NULL, that->m_spClientSite, 0, that->m_hWnd, &rcPos); |
|
1461 break; |
|
1462 |
|
1463 case WM_INITMENUPOPUP: |
|
1464 if (that->qt.widget) { |
|
1465 that->currentPopup = that->menuMap[(HMENU)wParam]; |
|
1466 if (!that->currentPopup) |
|
1467 break; |
|
1468 const QMetaObject *mo = that->currentPopup->metaObject(); |
|
1469 int index = mo->indexOfSignal("aboutToShow()"); |
|
1470 if (index < 0) |
|
1471 break; |
|
1472 |
|
1473 that->currentPopup->qt_metacall(QMetaObject::InvokeMetaMethod, index, 0); |
|
1474 that->createPopup(that->currentPopup, (HMENU)wParam); |
|
1475 return 0; |
|
1476 } |
|
1477 break; |
|
1478 |
|
1479 case WM_MENUSELECT: |
|
1480 case WM_COMMAND: |
|
1481 if (that->qt.widget) { |
|
1482 QMenuBar *menuBar = that->menuBar; |
|
1483 if (!menuBar) |
|
1484 break; |
|
1485 |
|
1486 QObject *menuObject = 0; |
|
1487 bool menuClosed = false; |
|
1488 |
|
1489 if (uMsg == WM_COMMAND) { |
|
1490 menuObject = that->actionMap.value(wParam); |
|
1491 } else if (!lParam) { |
|
1492 menuClosed = true; |
|
1493 menuObject = that->currentPopup; |
|
1494 } else { |
|
1495 menuObject = that->actionMap.value(LOWORD(wParam)); |
|
1496 } |
|
1497 |
|
1498 if (menuObject) { |
|
1499 const QMetaObject *mo = menuObject->metaObject(); |
|
1500 int index = -1; |
|
1501 |
|
1502 if (uMsg == WM_COMMAND) |
|
1503 index = mo->indexOfSignal("activated()"); |
|
1504 else if (menuClosed) |
|
1505 index = mo->indexOfSignal("aboutToHide()"); |
|
1506 else |
|
1507 index = mo->indexOfSignal("hovered()"); |
|
1508 |
|
1509 if (index < 0) |
|
1510 break; |
|
1511 |
|
1512 menuObject->qt_metacall(QMetaObject::InvokeMetaMethod, index, 0); |
|
1513 if (menuClosed || uMsg == WM_COMMAND) |
|
1514 that->currentPopup = 0; |
|
1515 return 0; |
|
1516 } |
|
1517 } |
|
1518 break; |
|
1519 |
|
1520 default: |
|
1521 break; |
|
1522 } |
|
1523 } |
|
1524 |
|
1525 return ::DefWindowProc(hWnd, uMsg, wParam, lParam); |
|
1526 } |
|
1527 |
|
1528 /*! |
|
1529 Creates the window hosting the QWidget. |
|
1530 */ |
|
1531 HWND QAxServerBase::create(HWND hWndParent, RECT& rcPos) |
|
1532 { |
|
1533 Q_ASSERT(isWidget && qt.widget); |
|
1534 |
|
1535 static ATOM atom = 0; |
|
1536 HINSTANCE hInst = (HINSTANCE)qAxInstance; |
|
1537 EnterCriticalSection(&createWindowSection); |
|
1538 QString cn(QLatin1String("QAxControl")); |
|
1539 cn += QString::number((int)ActiveXProc); |
|
1540 if (!atom) { |
|
1541 WNDCLASS wcTemp; |
|
1542 wcTemp.style = CS_DBLCLKS; |
|
1543 wcTemp.cbClsExtra = 0; |
|
1544 wcTemp.cbWndExtra = 0; |
|
1545 wcTemp.hbrBackground = 0; |
|
1546 wcTemp.hCursor = 0; |
|
1547 wcTemp.hIcon = 0; |
|
1548 wcTemp.hInstance = hInst; |
|
1549 wcTemp.lpszClassName = (wchar_t*)cn.utf16(); |
|
1550 wcTemp.lpszMenuName = 0; |
|
1551 wcTemp.lpfnWndProc = ActiveXProc; |
|
1552 |
|
1553 atom = RegisterClass(&wcTemp); |
|
1554 } |
|
1555 LeaveCriticalSection(&createWindowSection); |
|
1556 if (!atom && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) |
|
1557 return 0; |
|
1558 |
|
1559 Q_ASSERT(!m_hWnd); |
|
1560 HWND hWnd = ::CreateWindow((wchar_t*)cn.utf16(), 0, |
|
1561 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, |
|
1562 rcPos.left, rcPos.top, rcPos.right - rcPos.left, |
|
1563 rcPos.bottom - rcPos.top, hWndParent, 0, hInst, this); |
|
1564 |
|
1565 Q_ASSERT(m_hWnd == hWnd); |
|
1566 |
|
1567 updateMask(); |
|
1568 EnableWindow(m_hWnd, qt.widget->isEnabled()); |
|
1569 |
|
1570 return hWnd; |
|
1571 } |
|
1572 |
|
1573 /* |
|
1574 Recoursively creates Win32 submenus. |
|
1575 */ |
|
1576 HMENU QAxServerBase::createPopup(QMenu *popup, HMENU oldMenu) |
|
1577 { |
|
1578 HMENU popupMenu = oldMenu ? oldMenu : CreatePopupMenu(); |
|
1579 menuMap.insert(popupMenu, popup); |
|
1580 |
|
1581 if (oldMenu) while (GetMenuItemCount(oldMenu)) { |
|
1582 DeleteMenu(oldMenu, 0, MF_BYPOSITION); |
|
1583 } |
|
1584 |
|
1585 const QList<QAction*> actions = popup->actions(); |
|
1586 for (int i = 0; i < actions.count(); ++i) { |
|
1587 QAction *action = actions.at(i); |
|
1588 |
|
1589 uint flags = action->isEnabled() ? MF_ENABLED : MF_GRAYED; |
|
1590 if (action->isSeparator()) |
|
1591 flags |= MF_SEPARATOR; |
|
1592 else if (action->menu()) |
|
1593 flags |= MF_POPUP; |
|
1594 else |
|
1595 flags |= MF_STRING; |
|
1596 if (action->isChecked()) |
|
1597 flags |= MF_CHECKED; |
|
1598 |
|
1599 ushort itemId; |
|
1600 if (flags & MF_POPUP) { |
|
1601 itemId = static_cast<ushort>( |
|
1602 reinterpret_cast<ulong>(createPopup(action->menu())) |
|
1603 ); |
|
1604 } else { |
|
1605 itemId = static_cast<ushort>(reinterpret_cast<ulong>(action)); |
|
1606 actionMap.remove(itemId); |
|
1607 actionMap.insert(itemId, action); |
|
1608 } |
|
1609 AppendMenu(popupMenu, flags, itemId, (const wchar_t *)action->text().utf16()); |
|
1610 } |
|
1611 if (oldMenu) |
|
1612 DrawMenuBar(hwndMenuOwner); |
|
1613 return popupMenu; |
|
1614 } |
|
1615 |
|
1616 /*! |
|
1617 Creates a Win32 menubar. |
|
1618 */ |
|
1619 void QAxServerBase::createMenu(QMenuBar *menuBar) |
|
1620 { |
|
1621 hmenuShared = ::CreateMenu(); |
|
1622 |
|
1623 int edit = 0; |
|
1624 int object = 0; |
|
1625 int help = 0; |
|
1626 |
|
1627 const QList<QAction*> actions = menuBar->actions(); |
|
1628 for (int i = 0; i < actions.count(); ++i) { |
|
1629 QAction *action = actions.at(i); |
|
1630 |
|
1631 uint flags = action->isEnabled() ? MF_ENABLED : MF_GRAYED; |
|
1632 if (action->isSeparator()) |
|
1633 flags |= MF_SEPARATOR; |
|
1634 else if (action->menu()) |
|
1635 flags |= MF_POPUP; |
|
1636 else |
|
1637 flags |= MF_STRING; |
|
1638 |
|
1639 if (action->text() == QCoreApplication::translate(qt.widget->metaObject()->className(), "&Edit")) |
|
1640 edit++; |
|
1641 else if (action->text() == QCoreApplication::translate(qt.widget->metaObject()->className(), "&Help")) |
|
1642 help++; |
|
1643 else |
|
1644 object++; |
|
1645 |
|
1646 ushort itemId; |
|
1647 if (flags & MF_POPUP) { |
|
1648 itemId = static_cast<ushort>( |
|
1649 reinterpret_cast<ulong>(createPopup(action->menu())) |
|
1650 ); |
|
1651 } else { |
|
1652 itemId = static_cast<ushort>(reinterpret_cast<ulong>(action)); |
|
1653 actionMap.insert(itemId, action); |
|
1654 } |
|
1655 AppendMenu(hmenuShared, flags, itemId, (const wchar_t *)action->text().utf16()); |
|
1656 } |
|
1657 |
|
1658 OLEMENUGROUPWIDTHS menuWidths = {0,edit,0,object,0,help}; |
|
1659 HRESULT hres = m_spInPlaceFrame->InsertMenus(hmenuShared, &menuWidths); |
|
1660 if (FAILED(hres)) { |
|
1661 ::DestroyMenu(hmenuShared); |
|
1662 hmenuShared = 0; |
|
1663 return; |
|
1664 } |
|
1665 |
|
1666 m_spInPlaceFrame->GetWindow(&hwndMenuOwner); |
|
1667 |
|
1668 holemenu = OleCreateMenuDescriptor(hmenuShared, &menuWidths); |
|
1669 hres = m_spInPlaceFrame->SetMenu(hmenuShared, holemenu, m_hWnd); |
|
1670 if (FAILED(hres)) { |
|
1671 ::DestroyMenu(hmenuShared); |
|
1672 hmenuShared = 0; |
|
1673 OleDestroyMenuDescriptor(holemenu); |
|
1674 } |
|
1675 } |
|
1676 |
|
1677 /*! |
|
1678 Remove the Win32 menubar. |
|
1679 */ |
|
1680 void QAxServerBase::removeMenu() |
|
1681 { |
|
1682 if (hmenuShared) |
|
1683 m_spInPlaceFrame->RemoveMenus(hmenuShared); |
|
1684 holemenu = 0; |
|
1685 m_spInPlaceFrame->SetMenu(0, 0, m_hWnd); |
|
1686 if (hmenuShared) { |
|
1687 DestroyMenu(hmenuShared); |
|
1688 hmenuShared = 0; |
|
1689 menuMap.clear(); |
|
1690 } |
|
1691 hwndMenuOwner = 0; |
|
1692 } |
|
1693 |
|
1694 extern bool ignoreSlots(const char *test); |
|
1695 extern bool ignoreProps(const char *test); |
|
1696 |
|
1697 /*! |
|
1698 Makes sure the type info is loaded |
|
1699 */ |
|
1700 void QAxServerBase::ensureMetaData() |
|
1701 { |
|
1702 if (!m_spTypeInfo) { |
|
1703 qAxTypeLibrary->GetTypeInfoOfGuid(qAxFactory()->interfaceID(class_name), &m_spTypeInfo); |
|
1704 m_spTypeInfo->AddRef(); |
|
1705 } |
|
1706 } |
|
1707 |
|
1708 /*! |
|
1709 \internal |
|
1710 Returns true if the property \a index is exposed to COM and should |
|
1711 be saved/loaded. |
|
1712 */ |
|
1713 bool QAxServerBase::isPropertyExposed(int index) |
|
1714 { |
|
1715 if (!theObject) |
|
1716 return false; |
|
1717 |
|
1718 bool result = false; |
|
1719 const QMetaObject *mo = theObject->metaObject(); |
|
1720 |
|
1721 int qtProps = 0; |
|
1722 if (theObject->isWidgetType()) |
|
1723 qtProps = QWidget::staticMetaObject.propertyCount(); |
|
1724 QMetaProperty property = mo->property(index); |
|
1725 if (index <= qtProps && ignoreProps(property.name())) |
|
1726 return result; |
|
1727 |
|
1728 BSTR bstrNames = QStringToBSTR(QLatin1String(property.name())); |
|
1729 DISPID dispId; |
|
1730 GetIDsOfNames(IID_NULL, (BSTR*)&bstrNames, 1, LOCALE_USER_DEFAULT, &dispId); |
|
1731 result = dispId != DISPID_UNKNOWN; |
|
1732 SysFreeString(bstrNames); |
|
1733 |
|
1734 return result; |
|
1735 } |
|
1736 |
|
1737 |
|
1738 /*! |
|
1739 \internal |
|
1740 Updates the view, or asks the client site to do so. |
|
1741 */ |
|
1742 void QAxServerBase::update() |
|
1743 { |
|
1744 if (isInPlaceActive) { |
|
1745 if (m_hWnd) |
|
1746 ::InvalidateRect(m_hWnd, 0, true); |
|
1747 else if (m_spInPlaceSite) |
|
1748 m_spInPlaceSite->InvalidateRect(NULL, true); |
|
1749 } else if (m_spAdviseSink) { |
|
1750 m_spAdviseSink->OnViewChange(DVASPECT_CONTENT, -1); |
|
1751 for (int i = 0; i < adviseSinks.count(); ++i) { |
|
1752 adviseSinks.at(i).pAdvSink->OnViewChange(DVASPECT_CONTENT, -1); |
|
1753 } |
|
1754 } |
|
1755 } |
|
1756 |
|
1757 /*! |
|
1758 Resizes the control, faking a QResizeEvent if required |
|
1759 */ |
|
1760 void QAxServerBase::resize(const QSize &size) |
|
1761 { |
|
1762 if (!isWidget || !qt.widget || !size.isValid() || size == QSize(0, 0)) |
|
1763 return; |
|
1764 |
|
1765 QSize oldSize = qt.widget->size(); |
|
1766 qt.widget->resize(size); |
|
1767 QSize newSize = qt.widget->size(); |
|
1768 // make sure we get a resize event even if not embedded as a control |
|
1769 if (!m_hWnd && !qt.widget->isVisible() && newSize != oldSize) { |
|
1770 QResizeEvent resizeEvent(newSize, oldSize); |
|
1771 #ifndef QT_DLL // import from static library |
|
1772 extern bool qt_sendSpontaneousEvent(QObject*,QEvent*); |
|
1773 #endif |
|
1774 qt_sendSpontaneousEvent(qt.widget, &resizeEvent); |
|
1775 } |
|
1776 m_currentExtent = qt.widget->size(); |
|
1777 } |
|
1778 |
|
1779 /*! |
|
1780 \internal |
|
1781 |
|
1782 Updates the internal size values. |
|
1783 */ |
|
1784 void QAxServerBase::updateGeometry() |
|
1785 { |
|
1786 if (!isWidget || !qt.widget) |
|
1787 return; |
|
1788 |
|
1789 const QSize sizeHint = qt.widget->sizeHint(); |
|
1790 const QSize size = qt.widget->size(); |
|
1791 if (sizeHint.isValid()) { // if provided, adjust to sizeHint |
|
1792 QSize newSize = size; |
|
1793 if (!qt.widget->testAttribute(Qt::WA_Resized)) { |
|
1794 newSize = sizeHint; |
|
1795 } else { // according to sizePolicy rules if already resized |
|
1796 QSizePolicy sizePolicy = qt.widget->sizePolicy(); |
|
1797 if (sizeHint.width() > size.width() && !(sizePolicy.horizontalPolicy() & QSizePolicy::ShrinkFlag)) |
|
1798 newSize.setWidth(sizeHint.width()); |
|
1799 if (sizeHint.width() < size.width() && !(sizePolicy.horizontalPolicy() & QSizePolicy::GrowFlag)) |
|
1800 newSize.setWidth(sizeHint.width()); |
|
1801 if (sizeHint.height() > size.height() && !(sizePolicy.verticalPolicy() & QSizePolicy::ShrinkFlag)) |
|
1802 newSize.setHeight(sizeHint.height()); |
|
1803 if (sizeHint.height() < size.height() && !(sizePolicy.verticalPolicy() & QSizePolicy::GrowFlag)) |
|
1804 newSize.setHeight(sizeHint.height()); |
|
1805 } |
|
1806 resize(newSize); |
|
1807 |
|
1808 // set an initial size suitable for embedded controls |
|
1809 } else if (!qt.widget->testAttribute(Qt::WA_Resized)) { |
|
1810 resize(QSize(100, 100)); |
|
1811 qt.widget->setAttribute(Qt::WA_Resized, false); |
|
1812 } |
|
1813 } |
|
1814 |
|
1815 /*! |
|
1816 \internal |
|
1817 |
|
1818 Updates the mask of the widget parent. |
|
1819 */ |
|
1820 void QAxServerBase::updateMask() |
|
1821 { |
|
1822 if (!isWidget || !qt.widget || qt.widget->mask().isEmpty()) |
|
1823 return; |
|
1824 |
|
1825 QRegion rgn = qt.widget->mask(); |
|
1826 HRGN hrgn = rgn.handle(); |
|
1827 |
|
1828 // Since SetWindowRegion takes ownership |
|
1829 HRGN wr = CreateRectRgn(0,0,0,0); |
|
1830 CombineRgn(wr, hrgn, 0, RGN_COPY); |
|
1831 SetWindowRgn(m_hWnd, wr, true); |
|
1832 } |
|
1833 |
|
1834 static bool checkHRESULT(HRESULT hres) |
|
1835 { |
|
1836 const char *name = 0; |
|
1837 switch(hres) { |
|
1838 case S_OK: |
|
1839 return true; |
|
1840 case DISP_E_BADPARAMCOUNT: |
|
1841 #if defined(QT_CHECK_STATE) |
|
1842 qWarning("QAxBase: Error calling IDispatch member %s: Bad parameter count", name); |
|
1843 #endif |
|
1844 return false; |
|
1845 case DISP_E_BADVARTYPE: |
|
1846 #if defined(QT_CHECK_STATE) |
|
1847 qWarning("QAxBase: Error calling IDispatch member %s: Bad variant type", name); |
|
1848 #endif |
|
1849 return false; |
|
1850 case DISP_E_EXCEPTION: |
|
1851 #if defined(QT_CHECK_STATE) |
|
1852 qWarning("QAxBase: Error calling IDispatch member %s: Exception thrown by server", name); |
|
1853 #endif |
|
1854 return false; |
|
1855 case DISP_E_MEMBERNOTFOUND: |
|
1856 #if defined(QT_CHECK_STATE) |
|
1857 qWarning("QAxBase: Error calling IDispatch member %s: Member not found", name); |
|
1858 #endif |
|
1859 return false; |
|
1860 case DISP_E_NONAMEDARGS: |
|
1861 #if defined(QT_CHECK_STATE) |
|
1862 qWarning("QAxBase: Error calling IDispatch member %s: No named arguments", name); |
|
1863 #endif |
|
1864 return false; |
|
1865 case DISP_E_OVERFLOW: |
|
1866 #if defined(QT_CHECK_STATE) |
|
1867 qWarning("QAxBase: Error calling IDispatch member %s: Overflow", name); |
|
1868 #endif |
|
1869 return false; |
|
1870 case DISP_E_PARAMNOTFOUND: |
|
1871 #if defined(QT_CHECK_STATE) |
|
1872 qWarning("QAxBase: Error calling IDispatch member %s: Parameter not found", name); |
|
1873 #endif |
|
1874 return false; |
|
1875 case DISP_E_TYPEMISMATCH: |
|
1876 #if defined(QT_CHECK_STATE) |
|
1877 qWarning("QAxBase: Error calling IDispatch member %s: Type mismatch", name); |
|
1878 #endif |
|
1879 return false; |
|
1880 case DISP_E_UNKNOWNINTERFACE: |
|
1881 #if defined(QT_CHECK_STATE) |
|
1882 qWarning("QAxBase: Error calling IDispatch member %s: Unknown interface", name); |
|
1883 #endif |
|
1884 return false; |
|
1885 case DISP_E_UNKNOWNLCID: |
|
1886 #if defined(QT_CHECK_STATE) |
|
1887 qWarning("QAxBase: Error calling IDispatch member %s: Unknown locale ID", name); |
|
1888 #endif |
|
1889 return false; |
|
1890 case DISP_E_PARAMNOTOPTIONAL: |
|
1891 #if defined(QT_CHECK_STATE) |
|
1892 qWarning("QAxBase: Error calling IDispatch member %s: Non-optional parameter missing", name); |
|
1893 #endif |
|
1894 return false; |
|
1895 default: |
|
1896 #if defined(QT_CHECK_STATE) |
|
1897 qWarning("QAxBase: Error calling IDispatch member %s: Unknown error", name); |
|
1898 #endif |
|
1899 return false; |
|
1900 } |
|
1901 } |
|
1902 |
|
1903 static inline QByteArray paramType(const QByteArray &ptype, bool *out) |
|
1904 { |
|
1905 *out = ptype.endsWith('&') || ptype.endsWith("**"); |
|
1906 if (*out) { |
|
1907 QByteArray res(ptype); |
|
1908 res.truncate(res.length() - 1); |
|
1909 return res; |
|
1910 } |
|
1911 |
|
1912 return ptype; |
|
1913 } |
|
1914 |
|
1915 /*! |
|
1916 Catches all signals emitted by the Qt widget and fires the respective COM event. |
|
1917 |
|
1918 \a isignal is the Qt Meta Object index of the received signal, and \a _o the |
|
1919 signal parameters. |
|
1920 */ |
|
1921 int QAxServerBase::qt_metacall(QMetaObject::Call call, int index, void **argv) |
|
1922 { |
|
1923 Q_ASSERT(call == QMetaObject::InvokeMetaMethod); |
|
1924 |
|
1925 if (index == -1) { |
|
1926 if (sender() && m_spInPlaceFrame) { |
|
1927 if (qobject_cast<QStatusBar*>(sender()) != statusBar) |
|
1928 return true; |
|
1929 |
|
1930 if (statusBar->isHidden()) { |
|
1931 QString message = *(QString*)argv[1]; |
|
1932 m_spInPlaceFrame->SetStatusText(QStringToBSTR(message)); |
|
1933 } |
|
1934 } |
|
1935 return true; |
|
1936 } |
|
1937 |
|
1938 if (freezeEvents || inDesignMode) |
|
1939 return true; |
|
1940 |
|
1941 ensureMetaData(); |
|
1942 |
|
1943 // get the signal information. |
|
1944 const QMetaObject *mo = qt.object->metaObject(); |
|
1945 QMetaMethod signal; |
|
1946 DISPID eventId = index; |
|
1947 int pcount = 0; |
|
1948 QByteArray type; |
|
1949 QList<QByteArray> ptypes; |
|
1950 |
|
1951 switch(index) { |
|
1952 case DISPID_KEYDOWN: |
|
1953 case DISPID_KEYUP: |
|
1954 pcount = 2; |
|
1955 ptypes << "int&" << "int"; |
|
1956 break; |
|
1957 case DISPID_KEYPRESS: |
|
1958 pcount = 1; |
|
1959 ptypes << "int&"; |
|
1960 break; |
|
1961 case DISPID_MOUSEDOWN: |
|
1962 case DISPID_MOUSEMOVE: |
|
1963 case DISPID_MOUSEUP: |
|
1964 pcount = 4; |
|
1965 ptypes << "int" << "int" << "int" << "int"; |
|
1966 break; |
|
1967 case DISPID_CLICK: |
|
1968 pcount = 0; |
|
1969 break; |
|
1970 case DISPID_DBLCLICK: |
|
1971 pcount = 0; |
|
1972 break; |
|
1973 default: |
|
1974 { |
|
1975 signal = mo->method(index); |
|
1976 Q_ASSERT(signal.methodType() == QMetaMethod::Signal); |
|
1977 type = signal.typeName(); |
|
1978 QByteArray signature(signal.signature()); |
|
1979 QByteArray name(signature); |
|
1980 name.truncate(name.indexOf('(')); |
|
1981 |
|
1982 eventId = signalCache.value(index, -1); |
|
1983 if (eventId == -1) { |
|
1984 ITypeInfo *eventInfo = 0; |
|
1985 qAxTypeLibrary->GetTypeInfoOfGuid(qAxFactory()->eventsID(class_name), &eventInfo); |
|
1986 if (eventInfo) { |
|
1987 QString uni_name = QLatin1String(name); |
|
1988 const OLECHAR *olename = reinterpret_cast<const OLECHAR *>(uni_name.utf16()); |
|
1989 eventInfo->GetIDsOfNames((OLECHAR**)&olename, 1, &eventId); |
|
1990 eventInfo->Release(); |
|
1991 } |
|
1992 } |
|
1993 |
|
1994 signature = signature.mid(name.length() + 1); |
|
1995 signature.truncate(signature.length() - 1); |
|
1996 |
|
1997 if (!signature.isEmpty()) |
|
1998 ptypes = signature.split(','); |
|
1999 |
|
2000 pcount = ptypes.count(); |
|
2001 } |
|
2002 break; |
|
2003 } |
|
2004 if (pcount && !argv) { |
|
2005 qWarning("QAxServerBase::qt_metacall: Missing %d arguments", pcount); |
|
2006 return false; |
|
2007 } |
|
2008 if (eventId == -1) |
|
2009 return false; |
|
2010 |
|
2011 // For all connected event sinks... |
|
2012 IConnectionPoint *cpoint = 0; |
|
2013 GUID IID_QAxEvents = qAxFactory()->eventsID(class_name); |
|
2014 FindConnectionPoint(IID_QAxEvents, &cpoint); |
|
2015 if (cpoint) { |
|
2016 IEnumConnections *clist = 0; |
|
2017 cpoint->EnumConnections(&clist); |
|
2018 if (clist) { |
|
2019 clist->Reset(); |
|
2020 ULONG cc = 1; |
|
2021 CONNECTDATA c[1]; |
|
2022 clist->Next(cc, (CONNECTDATA*)&c, &cc); |
|
2023 if (cc) { |
|
2024 // setup parameters |
|
2025 unsigned int argErr = 0; |
|
2026 DISPPARAMS dispParams; |
|
2027 dispParams.cArgs = pcount; |
|
2028 dispParams.cNamedArgs = 0; |
|
2029 dispParams.rgdispidNamedArgs = 0; |
|
2030 dispParams.rgvarg = 0; |
|
2031 |
|
2032 if (pcount) // Use malloc/free for eval package compatibility |
|
2033 dispParams.rgvarg = (VARIANTARG*)malloc(pcount * sizeof(VARIANTARG)); |
|
2034 int p = 0; |
|
2035 for (p = 0; p < pcount; ++p) { |
|
2036 VARIANT *arg = dispParams.rgvarg + (pcount - p - 1); |
|
2037 VariantInit(arg); |
|
2038 |
|
2039 bool out; |
|
2040 QByteArray ptype = paramType(ptypes.at(p), &out); |
|
2041 QVariant variant; |
|
2042 if (mo->indexOfEnumerator(ptype) != -1) { |
|
2043 // convert enum values to int |
|
2044 variant = QVariant(*reinterpret_cast<int *>(argv[p+1])); |
|
2045 } else { |
|
2046 QVariant::Type vt = QVariant::nameToType(ptype); |
|
2047 if (vt == QVariant::UserType) { |
|
2048 if (ptype.endsWith('*')) { |
|
2049 variant = QVariant(QMetaType::type(ptype), (void**)argv[p+1]); |
|
2050 // qVariantSetValue(variant, *(void**)(argv[p + 1]), ptype); |
|
2051 } else { |
|
2052 variant = QVariant(QMetaType::type(ptype), argv[p+1]); |
|
2053 // qVariantSetValue(variant, argv[p + 1], ptype); |
|
2054 } |
|
2055 } else { |
|
2056 variant = QVariant(vt, argv[p + 1]); |
|
2057 } |
|
2058 } |
|
2059 |
|
2060 QVariantToVARIANT(variant, *arg, type, out); |
|
2061 } |
|
2062 |
|
2063 VARIANT retval; |
|
2064 VariantInit(&retval); |
|
2065 VARIANT *pretval = 0; |
|
2066 if (!type.isEmpty()) |
|
2067 pretval = &retval; |
|
2068 |
|
2069 // call listeners (through IDispatch) |
|
2070 while (cc) { |
|
2071 if (c->pUnk) { |
|
2072 IDispatch *disp = 0; |
|
2073 c->pUnk->QueryInterface(IID_QAxEvents, (void**)&disp); |
|
2074 if (disp) { |
|
2075 disp->Invoke(eventId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispParams, pretval, 0, &argErr); |
|
2076 |
|
2077 // update out-parameters and return value |
|
2078 if (index > 0) { |
|
2079 for (p = 0; p < pcount; ++p) { |
|
2080 bool out; |
|
2081 QByteArray ptype = paramType(ptypes.at(p), &out); |
|
2082 if (out) |
|
2083 QVariantToVoidStar(VARIANTToQVariant(dispParams.rgvarg[pcount - p - 1], ptype), argv[p+1], ptype); |
|
2084 } |
|
2085 if (pretval) |
|
2086 QVariantToVoidStar(VARIANTToQVariant(retval, type), argv[0], type); |
|
2087 } |
|
2088 disp->Release(); |
|
2089 } |
|
2090 c->pUnk->Release(); // AddRef'ed by clist->Next implementation |
|
2091 } |
|
2092 clist->Next(cc, (CONNECTDATA*)&c, &cc); |
|
2093 } |
|
2094 |
|
2095 // clean up |
|
2096 for (p = 0; p < pcount; ++p) |
|
2097 clearVARIANT(dispParams.rgvarg+p); |
|
2098 free(dispParams.rgvarg); |
|
2099 } |
|
2100 clist->Release(); |
|
2101 } |
|
2102 cpoint->Release(); |
|
2103 } |
|
2104 |
|
2105 return true; |
|
2106 } |
|
2107 |
|
2108 /*! |
|
2109 Call IPropertyNotifySink of connected clients. |
|
2110 \a dispId specifies the ID of the property that changed. |
|
2111 */ |
|
2112 bool QAxServerBase::emitRequestPropertyChange(const char *property) |
|
2113 { |
|
2114 long dispId = -1; |
|
2115 |
|
2116 IConnectionPoint *cpoint = 0; |
|
2117 FindConnectionPoint(IID_IPropertyNotifySink, &cpoint); |
|
2118 if (cpoint) { |
|
2119 IEnumConnections *clist = 0; |
|
2120 cpoint->EnumConnections(&clist); |
|
2121 if (clist) { |
|
2122 clist->Reset(); |
|
2123 ULONG cc = 1; |
|
2124 CONNECTDATA c[1]; |
|
2125 clist->Next(cc, (CONNECTDATA*)&c, &cc); |
|
2126 if (cc) { |
|
2127 if (dispId == -1) { |
|
2128 BSTR bstr = QStringToBSTR(QLatin1String(property)); |
|
2129 GetIDsOfNames(IID_NULL, &bstr, 1, LOCALE_USER_DEFAULT, &dispId); |
|
2130 SysFreeString(bstr); |
|
2131 } |
|
2132 if (dispId != -1) while (cc) { |
|
2133 if (c->pUnk) { |
|
2134 IPropertyNotifySink *sink = 0; |
|
2135 c->pUnk->QueryInterface(IID_IPropertyNotifySink, (void**)&sink); |
|
2136 bool disallows = sink && sink->OnRequestEdit(dispId) == S_FALSE; |
|
2137 sink->Release(); |
|
2138 c->pUnk->Release(); |
|
2139 if (disallows) { // a client disallows the property to change |
|
2140 clist->Release(); |
|
2141 cpoint->Release(); |
|
2142 return false; |
|
2143 } |
|
2144 } |
|
2145 clist->Next(cc, (CONNECTDATA*)&c, &cc); |
|
2146 } |
|
2147 } |
|
2148 clist->Release(); |
|
2149 } |
|
2150 cpoint->Release(); |
|
2151 } |
|
2152 dirtyflag = true; |
|
2153 return true; |
|
2154 } |
|
2155 |
|
2156 /*! |
|
2157 Call IPropertyNotifySink of connected clients. |
|
2158 \a dispId specifies the ID of the property that changed. |
|
2159 */ |
|
2160 void QAxServerBase::emitPropertyChanged(const char *property) |
|
2161 { |
|
2162 long dispId = -1; |
|
2163 |
|
2164 IConnectionPoint *cpoint = 0; |
|
2165 FindConnectionPoint(IID_IPropertyNotifySink, &cpoint); |
|
2166 if (cpoint) { |
|
2167 IEnumConnections *clist = 0; |
|
2168 cpoint->EnumConnections(&clist); |
|
2169 if (clist) { |
|
2170 clist->Reset(); |
|
2171 ULONG cc = 1; |
|
2172 CONNECTDATA c[1]; |
|
2173 clist->Next(cc, (CONNECTDATA*)&c, &cc); |
|
2174 if (cc) { |
|
2175 if (dispId == -1) { |
|
2176 BSTR bstr = QStringToBSTR(QLatin1String(property)); |
|
2177 GetIDsOfNames(IID_NULL, &bstr, 1, LOCALE_USER_DEFAULT, &dispId); |
|
2178 SysFreeString(bstr); |
|
2179 } |
|
2180 if (dispId != -1) while (cc) { |
|
2181 if (c->pUnk) { |
|
2182 IPropertyNotifySink *sink = 0; |
|
2183 c->pUnk->QueryInterface(IID_IPropertyNotifySink, (void**)&sink); |
|
2184 if (sink) { |
|
2185 sink->OnChanged(dispId); |
|
2186 sink->Release(); |
|
2187 } |
|
2188 c->pUnk->Release(); |
|
2189 } |
|
2190 clist->Next(cc, (CONNECTDATA*)&c, &cc); |
|
2191 } |
|
2192 } |
|
2193 clist->Release(); |
|
2194 } |
|
2195 cpoint->Release(); |
|
2196 } |
|
2197 dirtyflag = true; |
|
2198 } |
|
2199 |
|
2200 //**** IProvideClassInfo |
|
2201 /* |
|
2202 Provide the ITypeInfo implementation for the COM class. |
|
2203 */ |
|
2204 HRESULT WINAPI QAxServerBase::GetClassInfo(ITypeInfo** pptinfo) |
|
2205 { |
|
2206 if (!pptinfo) |
|
2207 return E_POINTER; |
|
2208 |
|
2209 *pptinfo = 0; |
|
2210 if (!qAxTypeLibrary) |
|
2211 return DISP_E_BADINDEX; |
|
2212 |
|
2213 return qAxTypeLibrary->GetTypeInfoOfGuid(qAxFactory()->classID(class_name), pptinfo); |
|
2214 } |
|
2215 |
|
2216 //**** IProvideClassInfo2 |
|
2217 /* |
|
2218 Provide the ID of the event interface. |
|
2219 */ |
|
2220 HRESULT WINAPI QAxServerBase::GetGUID(DWORD dwGuidKind, GUID* pGUID) |
|
2221 { |
|
2222 if (!pGUID) |
|
2223 return E_POINTER; |
|
2224 |
|
2225 if (dwGuidKind == GUIDKIND_DEFAULT_SOURCE_DISP_IID) { |
|
2226 *pGUID = qAxFactory()->eventsID(class_name); |
|
2227 return S_OK; |
|
2228 } |
|
2229 *pGUID = GUID_NULL; |
|
2230 return E_FAIL; |
|
2231 } |
|
2232 |
|
2233 //**** IDispatch |
|
2234 /* |
|
2235 Returns the number of class infos for this IDispatch. |
|
2236 */ |
|
2237 HRESULT WINAPI QAxServerBase::GetTypeInfoCount(UINT* pctinfo) |
|
2238 { |
|
2239 if (!pctinfo) |
|
2240 return E_POINTER; |
|
2241 |
|
2242 *pctinfo = qAxTypeLibrary ? 1 : 0; |
|
2243 return S_OK; |
|
2244 } |
|
2245 |
|
2246 /* |
|
2247 Provides the ITypeInfo for this IDispatch implementation. |
|
2248 */ |
|
2249 HRESULT WINAPI QAxServerBase::GetTypeInfo(UINT itinfo, LCID /*lcid*/, ITypeInfo** pptinfo) |
|
2250 { |
|
2251 if (!pptinfo) |
|
2252 return E_POINTER; |
|
2253 |
|
2254 if (!qAxTypeLibrary) |
|
2255 return DISP_E_BADINDEX; |
|
2256 |
|
2257 ensureMetaData(); |
|
2258 |
|
2259 *pptinfo = m_spTypeInfo; |
|
2260 (*pptinfo)->AddRef(); |
|
2261 |
|
2262 return S_OK; |
|
2263 } |
|
2264 |
|
2265 /* |
|
2266 Provides the names of the methods implemented in this IDispatch implementation. |
|
2267 */ |
|
2268 HRESULT WINAPI QAxServerBase::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, |
|
2269 LCID /*lcid*/, DISPID* rgdispid) |
|
2270 { |
|
2271 if (!rgszNames || !rgdispid) |
|
2272 return E_POINTER; |
|
2273 |
|
2274 if (!qAxTypeLibrary) |
|
2275 return DISP_E_UNKNOWNNAME; |
|
2276 |
|
2277 ensureMetaData(); |
|
2278 if (!m_spTypeInfo) |
|
2279 return DISP_E_UNKNOWNNAME; |
|
2280 |
|
2281 return m_spTypeInfo->GetIDsOfNames(rgszNames, cNames, rgdispid); |
|
2282 } |
|
2283 |
|
2284 /* |
|
2285 Map the COM call to the Qt slot/property for \a dispidMember. |
|
2286 */ |
|
2287 HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid, |
|
2288 LCID /*lcid*/, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult, |
|
2289 EXCEPINFO* pexcepinfo, UINT* puArgErr) |
|
2290 { |
|
2291 if (riid != IID_NULL) |
|
2292 return DISP_E_UNKNOWNINTERFACE; |
|
2293 if (!theObject) |
|
2294 return E_UNEXPECTED; |
|
2295 |
|
2296 HRESULT res = DISP_E_MEMBERNOTFOUND; |
|
2297 |
|
2298 bool uniqueIndex = wFlags == DISPATCH_PROPERTYGET || wFlags == DISPATCH_PROPERTYPUT || wFlags == DISPATCH_METHOD; |
|
2299 |
|
2300 int index = uniqueIndex ? indexCache.value(dispidMember, -1) : -1; |
|
2301 QByteArray name; |
|
2302 if (index == -1) { |
|
2303 ensureMetaData(); |
|
2304 |
|
2305 // This property or method is invoked when an ActiveX client specifies |
|
2306 // the object name without a property or method. We only support property. |
|
2307 if (dispidMember == DISPID_VALUE && (wFlags == DISPATCH_PROPERTYGET || wFlags == DISPATCH_PROPERTYPUT)) { |
|
2308 const QMetaObject *mo = qt.object->metaObject(); |
|
2309 index = mo->indexOfClassInfo("DefaultProperty"); |
|
2310 if (index != -1) { |
|
2311 name = mo->classInfo(index).value(); |
|
2312 index = mo->indexOfProperty(name); |
|
2313 } |
|
2314 } else { |
|
2315 BSTR bname; |
|
2316 UINT cname = 0; |
|
2317 if (m_spTypeInfo) |
|
2318 m_spTypeInfo->GetNames(dispidMember, &bname, 1, &cname); |
|
2319 if (!cname) |
|
2320 return res; |
|
2321 |
|
2322 name = QString::fromWCharArray(bname).toLatin1(); |
|
2323 SysFreeString(bname); |
|
2324 } |
|
2325 } |
|
2326 |
|
2327 const QMetaObject *mo = qt.object->metaObject(); |
|
2328 QSize oldSizeHint; |
|
2329 if (isWidget) |
|
2330 oldSizeHint = qt.widget->sizeHint(); |
|
2331 |
|
2332 switch (wFlags) { |
|
2333 case DISPATCH_PROPERTYGET|DISPATCH_METHOD: |
|
2334 case DISPATCH_PROPERTYGET: |
|
2335 { |
|
2336 if (index == -1) { |
|
2337 index = mo->indexOfProperty(name); |
|
2338 if (index == -1 && wFlags == DISPATCH_PROPERTYGET) |
|
2339 return res; |
|
2340 } |
|
2341 |
|
2342 QMetaProperty property; |
|
2343 if (index < mo->propertyCount()) |
|
2344 property = mo->property(index); |
|
2345 |
|
2346 if (property.isReadable()) { |
|
2347 if (!pvarResult) |
|
2348 return DISP_E_PARAMNOTOPTIONAL; |
|
2349 if (pDispParams->cArgs || |
|
2350 pDispParams->cNamedArgs) |
|
2351 return DISP_E_BADPARAMCOUNT; |
|
2352 |
|
2353 QVariant var = qt.object->property(property.name()); |
|
2354 if (!var.isValid()) |
|
2355 res = DISP_E_MEMBERNOTFOUND; |
|
2356 else if (!QVariantToVARIANT(var, *pvarResult)) |
|
2357 res = DISP_E_TYPEMISMATCH; |
|
2358 else |
|
2359 res = S_OK; |
|
2360 break; |
|
2361 } else if (wFlags == DISPATCH_PROPERTYGET) { |
|
2362 break; |
|
2363 } |
|
2364 } |
|
2365 // FALLTHROUGH if wFlags == DISPATCH_PROPERTYGET|DISPATCH_METHOD AND not a property. |
|
2366 case DISPATCH_METHOD: |
|
2367 { |
|
2368 int nameLength = 0; |
|
2369 if (index == -1) { |
|
2370 nameLength = name.length(); |
|
2371 name += '('; |
|
2372 // no parameter - shortcut |
|
2373 if (!pDispParams->cArgs) |
|
2374 index = mo->indexOfSlot((name + ')')); |
|
2375 // search |
|
2376 if (index == -1) { |
|
2377 for (int i = 0; i < mo->methodCount(); ++i) { |
|
2378 const QMetaMethod slot(mo->method(i)); |
|
2379 if (slot.methodType() == QMetaMethod::Slot && QByteArray(slot.signature()).startsWith(name)) { |
|
2380 index = i; |
|
2381 break; |
|
2382 } |
|
2383 } |
|
2384 // resolve overloads |
|
2385 if (index == -1) { |
|
2386 QRegExp regexp(QLatin1String("_([0-9])\\(")); |
|
2387 if (regexp.lastIndexIn(QString::fromLatin1(name.constData())) != -1) { |
|
2388 name = name.left(name.length() - regexp.cap(0).length()) + '('; |
|
2389 int overload = regexp.cap(1).toInt() + 1; |
|
2390 |
|
2391 for (int s = 0; s < qt.object->metaObject()->methodCount(); ++s) { |
|
2392 QMetaMethod slot = qt.object->metaObject()->method(s); |
|
2393 if (slot.methodType() == QMetaMethod::Slot && QByteArray(slot.signature()).startsWith(name)) { |
|
2394 if (!--overload) { |
|
2395 index = s; |
|
2396 break; |
|
2397 } |
|
2398 } |
|
2399 } |
|
2400 } |
|
2401 } |
|
2402 if (index == -1) |
|
2403 return res; |
|
2404 } |
|
2405 } |
|
2406 |
|
2407 int lookupIndex = index; |
|
2408 |
|
2409 // get slot info |
|
2410 QMetaMethod slot(mo->method(index)); |
|
2411 Q_ASSERT(slot.methodType() == QMetaMethod::Slot); |
|
2412 QByteArray type = slot.typeName(); |
|
2413 name = slot.signature(); |
|
2414 nameLength = name.indexOf('('); |
|
2415 QByteArray prototype = name.mid(nameLength + 1); |
|
2416 prototype.truncate(prototype.length() - 1); |
|
2417 QList<QByteArray> ptypes; |
|
2418 if (!prototype.isEmpty()) |
|
2419 ptypes = prototype.split(','); |
|
2420 int pcount = ptypes.count(); |
|
2421 |
|
2422 // verify parameter count |
|
2423 if (pcount > pDispParams->cArgs) { |
|
2424 // count cloned slots immediately following the real thing |
|
2425 int defArgs = 0; |
|
2426 while (index < mo->methodCount()) { |
|
2427 ++index; |
|
2428 slot = mo->method(index); |
|
2429 if (!(slot.attributes() & QMetaMethod::Cloned)) |
|
2430 break; |
|
2431 --pcount; |
|
2432 // found a matching overload. ptypes still valid |
|
2433 if (pcount <= pDispParams->cArgs) |
|
2434 break; |
|
2435 } |
|
2436 // still wrong :( |
|
2437 if (pcount > pDispParams->cArgs) |
|
2438 return DISP_E_PARAMNOTOPTIONAL; |
|
2439 } else if (pcount < pDispParams->cArgs) { |
|
2440 return DISP_E_BADPARAMCOUNT; |
|
2441 } |
|
2442 |
|
2443 // setup parameters (pcount + return) |
|
2444 bool ok = true; |
|
2445 void *static_argv[QAX_NUM_PARAMS + 1]; |
|
2446 QVariant static_varp[QAX_NUM_PARAMS + 1]; |
|
2447 void *static_argv_pointer[QAX_NUM_PARAMS + 1]; |
|
2448 |
|
2449 int totalParam = pcount; |
|
2450 if (!type.isEmpty()) |
|
2451 ++totalParam; |
|
2452 |
|
2453 void **argv = 0; // the actual array passed into qt_metacall |
|
2454 void **argv_pointer = 0; // in case we need an additional level of indirection |
|
2455 QVariant *varp = 0; // QVariants to hold the temporary Qt data object for us |
|
2456 |
|
2457 if (totalParam) { |
|
2458 if (totalParam <= QAX_NUM_PARAMS) { |
|
2459 argv = static_argv; |
|
2460 argv_pointer = static_argv_pointer; |
|
2461 varp = static_varp; |
|
2462 } else { |
|
2463 argv = new void*[pcount + 1]; |
|
2464 argv_pointer = new void*[pcount + 1]; |
|
2465 varp = new QVariant[pcount + 1]; |
|
2466 } |
|
2467 |
|
2468 argv_pointer[0] = 0; |
|
2469 } |
|
2470 |
|
2471 for (int p = 0; p < pcount; ++p) { |
|
2472 // map the VARIANT to the void* |
|
2473 bool out; |
|
2474 QByteArray ptype = paramType(ptypes.at(p), &out); |
|
2475 varp[p + 1] = VARIANTToQVariant(pDispParams->rgvarg[pcount - p - 1], ptype); |
|
2476 argv_pointer[p + 1] = 0; |
|
2477 if (varp[p + 1].isValid()) { |
|
2478 if (varp[p + 1].type() == QVariant::UserType) { |
|
2479 argv[p + 1] = varp[p + 1].data(); |
|
2480 } else if (ptype == "QVariant") { |
|
2481 argv[p + 1] = varp + p + 1; |
|
2482 } else { |
|
2483 argv[p + 1] = const_cast<void*>(varp[p + 1].constData()); |
|
2484 if (ptype.endsWith('*')) { |
|
2485 argv_pointer[p + 1] = argv[p + 1]; |
|
2486 argv[p + 1] = argv_pointer + p + 1; |
|
2487 } |
|
2488 } |
|
2489 } else if (ptype == "QVariant") { |
|
2490 argv[p + 1] = varp + p + 1; |
|
2491 } else { |
|
2492 if (puArgErr) |
|
2493 *puArgErr = pcount-p-1; |
|
2494 ok = false; |
|
2495 } |
|
2496 } |
|
2497 |
|
2498 // return value |
|
2499 if (!type.isEmpty()) { |
|
2500 QVariant::Type vt = QVariant::nameToType(type); |
|
2501 if (vt == QVariant::UserType) |
|
2502 vt = QVariant::Invalid; |
|
2503 varp[0] = QVariant(vt); |
|
2504 if (varp[0].type() == QVariant::Invalid && mo->indexOfEnumerator(slot.typeName()) != -1) |
|
2505 varp[0] = QVariant(QVariant::Int); |
|
2506 |
|
2507 if (varp[0].type() == QVariant::Invalid) { |
|
2508 if (type == "QVariant") |
|
2509 argv[0] = varp; |
|
2510 else |
|
2511 argv[0] = 0; |
|
2512 } else { |
|
2513 argv[0] = const_cast<void*>(varp[0].constData()); |
|
2514 } |
|
2515 if (type.endsWith('*')) { |
|
2516 argv_pointer[0] = argv[0]; |
|
2517 argv[0] = argv_pointer; |
|
2518 } |
|
2519 } |
|
2520 |
|
2521 // call the slot if everthing went fine. |
|
2522 if (ok) { |
|
2523 ++invokeCount; |
|
2524 qt.object->qt_metacall(QMetaObject::InvokeMetaMethod, index, argv); |
|
2525 if (--invokeCount < 0) |
|
2526 invokeCount = 0; |
|
2527 |
|
2528 // update reference parameters and return value |
|
2529 for (int p = 0; p < pcount; ++p) { |
|
2530 bool out; |
|
2531 QByteArray ptype = paramType(ptypes.at(p), &out); |
|
2532 if (out) { |
|
2533 if (!QVariantToVARIANT(varp[p + 1], pDispParams->rgvarg[pcount - p - 1], ptype, out)) |
|
2534 ok = false; |
|
2535 } |
|
2536 } |
|
2537 if (!type.isEmpty() && pvarResult) { |
|
2538 if (!varp[0].isValid() && type != "QVariant") |
|
2539 varp[0] = QVariant(QMetaType::type(type), argv_pointer); |
|
2540 // qVariantSetValue(varp[0], argv_pointer[0], type); |
|
2541 ok = QVariantToVARIANT(varp[0], *pvarResult, type); |
|
2542 } |
|
2543 } |
|
2544 if (argv && argv != static_argv) { |
|
2545 delete []argv; |
|
2546 delete []argv_pointer; |
|
2547 delete []varp; |
|
2548 } |
|
2549 |
|
2550 res = ok ? S_OK : DISP_E_TYPEMISMATCH; |
|
2551 |
|
2552 // reset in case index changed for default-arg handling |
|
2553 index = lookupIndex; |
|
2554 } |
|
2555 break; |
|
2556 case DISPATCH_PROPERTYPUT: |
|
2557 case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: |
|
2558 { |
|
2559 if (index == -1) { |
|
2560 index = mo->indexOfProperty(name); |
|
2561 if (index == -1) |
|
2562 return res; |
|
2563 } |
|
2564 |
|
2565 QMetaProperty property; |
|
2566 if (index < mo->propertyCount()) |
|
2567 property = mo->property(index); |
|
2568 if (!property.isWritable()) |
|
2569 return DISP_E_MEMBERNOTFOUND; |
|
2570 if (!pDispParams->cArgs) |
|
2571 return DISP_E_PARAMNOTOPTIONAL; |
|
2572 if (pDispParams->cArgs != 1 || |
|
2573 pDispParams->cNamedArgs != 1 || |
|
2574 *pDispParams->rgdispidNamedArgs != DISPID_PROPERTYPUT) |
|
2575 return DISP_E_BADPARAMCOUNT; |
|
2576 |
|
2577 QVariant var = VARIANTToQVariant(*pDispParams->rgvarg, property.typeName(), property.type()); |
|
2578 if (!var.isValid()) { |
|
2579 if (puArgErr) |
|
2580 *puArgErr = 0; |
|
2581 return DISP_E_BADVARTYPE; |
|
2582 } |
|
2583 if (!qt.object->setProperty(property.name(), var)) { |
|
2584 if (puArgErr) |
|
2585 *puArgErr = 0; |
|
2586 return DISP_E_TYPEMISMATCH; |
|
2587 } |
|
2588 |
|
2589 res = S_OK; |
|
2590 } |
|
2591 break; |
|
2592 |
|
2593 default: |
|
2594 break; |
|
2595 } |
|
2596 |
|
2597 // maybe calling a setter? Notify client about changes |
|
2598 switch(wFlags) { |
|
2599 case DISPATCH_METHOD: |
|
2600 case DISPATCH_PROPERTYPUT: |
|
2601 case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: |
|
2602 if (m_spAdviseSink || adviseSinks.count()) { |
|
2603 FORMATETC fmt; |
|
2604 fmt.cfFormat = 0; |
|
2605 fmt.ptd = 0; |
|
2606 fmt.dwAspect = DVASPECT_CONTENT; |
|
2607 fmt.lindex = -1; |
|
2608 fmt.tymed = TYMED_NULL; |
|
2609 |
|
2610 STGMEDIUM stg; |
|
2611 stg.tymed = TYMED_NULL; |
|
2612 stg.pUnkForRelease = 0; |
|
2613 stg.hBitmap = 0; // initializes the whole union |
|
2614 |
|
2615 if (m_spAdviseSink) { |
|
2616 m_spAdviseSink->OnViewChange(DVASPECT_CONTENT, -1); |
|
2617 m_spAdviseSink->OnDataChange(&fmt, &stg); |
|
2618 } |
|
2619 for (int i = 0; i < adviseSinks.count(); ++i) { |
|
2620 adviseSinks.at(i).pAdvSink->OnDataChange(&fmt, &stg); |
|
2621 } |
|
2622 } |
|
2623 |
|
2624 dirtyflag = true; |
|
2625 break; |
|
2626 default: |
|
2627 break; |
|
2628 } |
|
2629 |
|
2630 if (index != -1 && uniqueIndex) |
|
2631 indexCache.insert(dispidMember, index); |
|
2632 |
|
2633 if (exception) { |
|
2634 if (pexcepinfo) { |
|
2635 memset(pexcepinfo, 0, sizeof(EXCEPINFO)); |
|
2636 |
|
2637 pexcepinfo->wCode = exception->code; |
|
2638 if (!exception->src.isNull()) |
|
2639 pexcepinfo->bstrSource = QStringToBSTR(exception->src); |
|
2640 if (!exception->desc.isNull()) |
|
2641 pexcepinfo->bstrDescription = QStringToBSTR(exception->desc); |
|
2642 if (!exception->context.isNull()) { |
|
2643 QString context = exception->context; |
|
2644 int contextID = 0; |
|
2645 int br = context.indexOf(QLatin1Char('[')); |
|
2646 if (br != -1) { |
|
2647 context = context.mid(br+1); |
|
2648 context = context.left(context.length() - 1); |
|
2649 contextID = context.toInt(); |
|
2650 |
|
2651 context = exception->context; |
|
2652 context = context.left(br-1); |
|
2653 } |
|
2654 pexcepinfo->bstrHelpFile = QStringToBSTR(context); |
|
2655 pexcepinfo->dwHelpContext = contextID; |
|
2656 } |
|
2657 } |
|
2658 delete exception; |
|
2659 exception = 0; |
|
2660 return DISP_E_EXCEPTION; |
|
2661 } else if (isWidget) { |
|
2662 QSize sizeHint = qt.widget->sizeHint(); |
|
2663 if (oldSizeHint != sizeHint) { |
|
2664 updateGeometry(); |
|
2665 if (m_spInPlaceSite) { |
|
2666 RECT rect = {0, 0, sizeHint.width(), sizeHint.height()}; |
|
2667 m_spInPlaceSite->OnPosRectChange(&rect); |
|
2668 } |
|
2669 } |
|
2670 updateMask(); |
|
2671 } |
|
2672 |
|
2673 return res; |
|
2674 } |
|
2675 |
|
2676 //**** IConnectionPointContainer |
|
2677 /* |
|
2678 Provide the IEnumConnectionPoints implemented in the QAxSignalVec class. |
|
2679 */ |
|
2680 HRESULT WINAPI QAxServerBase::EnumConnectionPoints(IEnumConnectionPoints **epoints) |
|
2681 { |
|
2682 if (!epoints) |
|
2683 return E_POINTER; |
|
2684 *epoints = new QAxSignalVec(points); |
|
2685 (*epoints)->AddRef(); |
|
2686 return S_OK; |
|
2687 } |
|
2688 |
|
2689 /* |
|
2690 Provide the IConnectionPoint implemented in the QAxConnection for \a iid. |
|
2691 */ |
|
2692 HRESULT WINAPI QAxServerBase::FindConnectionPoint(REFIID iid, IConnectionPoint **cpoint) |
|
2693 { |
|
2694 if (!cpoint) |
|
2695 return E_POINTER; |
|
2696 |
|
2697 IConnectionPoint *cp = points[iid]; |
|
2698 *cpoint = cp; |
|
2699 if (cp) { |
|
2700 cp->AddRef(); |
|
2701 return S_OK; |
|
2702 } |
|
2703 return CONNECT_E_NOCONNECTION; |
|
2704 } |
|
2705 |
|
2706 //**** IPersistStream |
|
2707 /* |
|
2708 \reimp |
|
2709 |
|
2710 See documentation of IPersistStorage::IsDirty. |
|
2711 */ |
|
2712 HRESULT WINAPI QAxServerBase::IsDirty() |
|
2713 { |
|
2714 return dirtyflag ? S_OK : S_FALSE; |
|
2715 } |
|
2716 |
|
2717 HRESULT WINAPI QAxServerBase::Load(IStream *pStm) |
|
2718 { |
|
2719 STATSTG stat; |
|
2720 HRESULT hres = pStm->Stat(&stat, STATFLAG_DEFAULT); |
|
2721 bool openAsText = false; |
|
2722 QByteArray qtarray; |
|
2723 if (hres == S_OK) { |
|
2724 QString streamName = QString::fromWCharArray(stat.pwcsName); |
|
2725 CoTaskMemFree(stat.pwcsName); |
|
2726 openAsText = streamName == QLatin1String("SomeStreamName"); |
|
2727 if (stat.cbSize.HighPart) // more than 4GB - too large! |
|
2728 return S_FALSE; |
|
2729 |
|
2730 qtarray.resize(stat.cbSize.LowPart); |
|
2731 ULONG read; |
|
2732 pStm->Read(qtarray.data(), stat.cbSize.LowPart, &read); |
|
2733 } |
|
2734 const QMetaObject *mo = qt.object->metaObject(); |
|
2735 |
|
2736 QBuffer qtbuffer(&qtarray); |
|
2737 QByteArray mimeType = mo->classInfo(mo->indexOfClassInfo("MIME")).value(); |
|
2738 if (!mimeType.isEmpty()) { |
|
2739 mimeType = mimeType.left(mimeType.indexOf(':')); // first type |
|
2740 QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable"); |
|
2741 if (axb && axb->readData(&qtbuffer, QString::fromLatin1(mimeType))) |
|
2742 return S_OK; |
|
2743 } |
|
2744 |
|
2745 qtbuffer.close(); // resets |
|
2746 qtbuffer.open(openAsText ? (QIODevice::ReadOnly | QIODevice::Text) : QIODevice::ReadOnly); |
|
2747 |
|
2748 QDataStream qtstream(&qtbuffer); |
|
2749 int version; |
|
2750 qtstream >> version; |
|
2751 qtstream.setVersion(version); |
|
2752 int more = 0; |
|
2753 qtstream >> more; |
|
2754 |
|
2755 while (!qtbuffer.atEnd() && more) { |
|
2756 QString propname; |
|
2757 QVariant value; |
|
2758 qtstream >> propname; |
|
2759 if (propname.isEmpty()) |
|
2760 break; |
|
2761 qtstream >> value; |
|
2762 qtstream >> more; |
|
2763 |
|
2764 int idx = mo->indexOfProperty(propname.toLatin1()); |
|
2765 QMetaProperty property = mo->property(idx); |
|
2766 if (property.isWritable()) |
|
2767 qt.object->setProperty(propname.toLatin1(), value); |
|
2768 } |
|
2769 return S_OK; |
|
2770 } |
|
2771 |
|
2772 HRESULT WINAPI QAxServerBase::Save(IStream *pStm, BOOL clearDirty) |
|
2773 { |
|
2774 const QMetaObject *mo = qt.object->metaObject(); |
|
2775 |
|
2776 QBuffer qtbuffer; |
|
2777 bool saved = false; |
|
2778 QByteArray mimeType = mo->classInfo(mo->indexOfClassInfo("MIME")).value(); |
|
2779 if (!mimeType.isEmpty()) { |
|
2780 QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable"); |
|
2781 saved = axb && axb->writeData(&qtbuffer); |
|
2782 qtbuffer.close(); |
|
2783 } |
|
2784 |
|
2785 if (!saved) { |
|
2786 qtbuffer.open(QIODevice::WriteOnly); |
|
2787 QDataStream qtstream(&qtbuffer); |
|
2788 qtstream << qtstream.version(); |
|
2789 |
|
2790 for (int prop = 0; prop < mo->propertyCount(); ++prop) { |
|
2791 if (!isPropertyExposed(prop)) |
|
2792 continue; |
|
2793 QMetaProperty metaprop = mo->property(prop); |
|
2794 if (QByteArray(metaprop.typeName()).endsWith('*')) |
|
2795 continue; |
|
2796 QString property = QLatin1String(metaprop.name()); |
|
2797 QVariant qvar = qt.object->property(metaprop.name()); |
|
2798 if (qvar.isValid()) { |
|
2799 qtstream << int(1); |
|
2800 qtstream << property; |
|
2801 qtstream << qvar; |
|
2802 } |
|
2803 } |
|
2804 |
|
2805 qtstream << int(0); |
|
2806 qtbuffer.close(); |
|
2807 } |
|
2808 |
|
2809 QByteArray qtarray = qtbuffer.buffer(); |
|
2810 ULONG written = 0; |
|
2811 const char *data = qtarray.constData(); |
|
2812 ULARGE_INTEGER newsize; |
|
2813 newsize.HighPart = 0; |
|
2814 newsize.LowPart = qtarray.size(); |
|
2815 pStm->SetSize(newsize); |
|
2816 pStm->Write(data, qtarray.size(), &written); |
|
2817 pStm->Commit(STGC_ONLYIFCURRENT); |
|
2818 |
|
2819 if (clearDirty) |
|
2820 dirtyflag = false; |
|
2821 return S_OK; |
|
2822 } |
|
2823 |
|
2824 HRESULT WINAPI QAxServerBase::GetSizeMax(ULARGE_INTEGER *pcbSize) |
|
2825 { |
|
2826 const QMetaObject *mo = qt.object->metaObject(); |
|
2827 |
|
2828 int np = mo->propertyCount(); |
|
2829 pcbSize->HighPart = 0; |
|
2830 pcbSize->LowPart = np * 50; |
|
2831 |
|
2832 return S_OK; |
|
2833 } |
|
2834 |
|
2835 //**** IPersistStorage |
|
2836 |
|
2837 HRESULT WINAPI QAxServerBase::InitNew(IStorage *pStg) |
|
2838 { |
|
2839 if (initNewCalled) |
|
2840 return CO_E_ALREADYINITIALIZED; |
|
2841 |
|
2842 dirtyflag = false; |
|
2843 initNewCalled = true; |
|
2844 |
|
2845 m_spStorage = pStg; |
|
2846 if (m_spStorage) |
|
2847 m_spStorage->AddRef(); |
|
2848 return S_OK; |
|
2849 } |
|
2850 |
|
2851 HRESULT WINAPI QAxServerBase::Load(IStorage *pStg) |
|
2852 { |
|
2853 if (InitNew(pStg) != S_OK) |
|
2854 return CO_E_ALREADYINITIALIZED; |
|
2855 |
|
2856 IStream *spStream = 0; |
|
2857 QString streamName = QLatin1String(qt.object->metaObject()->className()); |
|
2858 streamName.replace(QLatin1Char(':'), QLatin1Char('.')); |
|
2859 /* Also invalid, but not relevant |
|
2860 streamName.replace(QLatin1Char('/'), QLatin1Char('_')); |
|
2861 streamName.replace(QLatin1Char('\\'), QLatin1Char('_')); |
|
2862 */ |
|
2863 streamName += QLatin1String("_Stream4.2"); |
|
2864 |
|
2865 pStg->OpenStream((const wchar_t *)streamName.utf16(), 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &spStream); |
|
2866 if (!spStream) // support for streams saved with 4.1 and earlier |
|
2867 pStg->OpenStream(L"SomeStreamName", 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &spStream); |
|
2868 if (!spStream) |
|
2869 return E_FAIL; |
|
2870 |
|
2871 Load(spStream); |
|
2872 spStream->Release(); |
|
2873 |
|
2874 return S_OK; |
|
2875 } |
|
2876 |
|
2877 HRESULT WINAPI QAxServerBase::Save(IStorage *pStg, BOOL fSameAsLoad) |
|
2878 { |
|
2879 IStream *spStream = 0; |
|
2880 QString streamName = QLatin1String(qt.object->metaObject()->className()); |
|
2881 streamName.replace(QLatin1Char(':'), QLatin1Char('.')); |
|
2882 /* Also invalid, but not relevant |
|
2883 streamName.replace(QLatin1Char('/'), QLatin1Char('_')); |
|
2884 streamName.replace(QLatin1Char('\\'), QLatin1Char('_')); |
|
2885 */ |
|
2886 streamName += QLatin1String("_Stream4.2"); |
|
2887 |
|
2888 pStg->CreateStream((const wchar_t *)streamName.utf16(), STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &spStream); |
|
2889 if (!spStream) |
|
2890 return E_FAIL; |
|
2891 |
|
2892 Save(spStream, true); |
|
2893 |
|
2894 spStream->Release(); |
|
2895 return S_OK; |
|
2896 } |
|
2897 |
|
2898 HRESULT WINAPI QAxServerBase::SaveCompleted(IStorage *pStgNew) |
|
2899 { |
|
2900 if (pStgNew) { |
|
2901 if (m_spStorage) |
|
2902 m_spStorage->Release(); |
|
2903 m_spStorage = pStgNew; |
|
2904 m_spStorage->AddRef(); |
|
2905 } |
|
2906 return S_OK; |
|
2907 } |
|
2908 |
|
2909 HRESULT WINAPI QAxServerBase::HandsOffStorage() |
|
2910 { |
|
2911 if (m_spStorage) m_spStorage->Release(); |
|
2912 m_spStorage = 0; |
|
2913 |
|
2914 return S_OK; |
|
2915 } |
|
2916 |
|
2917 //**** IPersistPropertyBag |
|
2918 /* |
|
2919 Initialize the properties of the Qt widget. |
|
2920 */ |
|
2921 HRESULT WINAPI QAxServerBase::InitNew() |
|
2922 { |
|
2923 if (initNewCalled) |
|
2924 return CO_E_ALREADYINITIALIZED; |
|
2925 |
|
2926 dirtyflag = false; |
|
2927 initNewCalled = true; |
|
2928 return S_OK; |
|
2929 } |
|
2930 |
|
2931 /* |
|
2932 Set the properties of the Qt widget to the values provided in the \a bag. |
|
2933 */ |
|
2934 HRESULT WINAPI QAxServerBase::Load(IPropertyBag *bag, IErrorLog * /*log*/) |
|
2935 { |
|
2936 if (!bag) |
|
2937 return E_POINTER; |
|
2938 |
|
2939 if (InitNew() != S_OK) |
|
2940 return E_UNEXPECTED; |
|
2941 |
|
2942 bool error = false; |
|
2943 const QMetaObject *mo = qt.object->metaObject(); |
|
2944 for (int prop = 0; prop < mo->propertyCount(); ++prop) { |
|
2945 if (!isPropertyExposed(prop)) |
|
2946 continue; |
|
2947 QMetaProperty property = mo->property(prop); |
|
2948 const char* pname = property.name(); |
|
2949 BSTR bstr = QStringToBSTR(QLatin1String(pname)); |
|
2950 VARIANT var; |
|
2951 var.vt = VT_EMPTY; |
|
2952 HRESULT res = bag->Read(bstr, &var, 0); |
|
2953 if (property.isWritable() && var.vt != VT_EMPTY) { |
|
2954 if (res != S_OK || !qt.object->setProperty(pname, VARIANTToQVariant(var, property.typeName(), property.type()))) |
|
2955 error = true; |
|
2956 } |
|
2957 SysFreeString(bstr); |
|
2958 } |
|
2959 |
|
2960 updateGeometry(); |
|
2961 |
|
2962 return /*error ? E_FAIL :*/ S_OK; |
|
2963 } |
|
2964 |
|
2965 /* |
|
2966 Save the properties of the Qt widget into the \a bag. |
|
2967 */ |
|
2968 HRESULT WINAPI QAxServerBase::Save(IPropertyBag *bag, BOOL clearDirty, BOOL /*saveAll*/) |
|
2969 { |
|
2970 if (!bag) |
|
2971 return E_POINTER; |
|
2972 |
|
2973 if (clearDirty) |
|
2974 dirtyflag = false; |
|
2975 bool error = false; |
|
2976 const QMetaObject *mo = qt.object->metaObject(); |
|
2977 for (int prop = 0; prop < mo->propertyCount(); ++prop) { |
|
2978 if (!isPropertyExposed(prop)) |
|
2979 continue; |
|
2980 QMetaProperty property = mo->property(prop); |
|
2981 if (QByteArray(property.typeName()).endsWith('*')) |
|
2982 continue; |
|
2983 |
|
2984 BSTR bstr = QStringToBSTR(QLatin1String(property.name())); |
|
2985 QVariant qvar = qt.object->property(property.name()); |
|
2986 if (!qvar.isValid()) |
|
2987 error = true; |
|
2988 VARIANT var; |
|
2989 QVariantToVARIANT(qvar, var); |
|
2990 bag->Write(bstr, &var); |
|
2991 SysFreeString(bstr); |
|
2992 } |
|
2993 return /*error ? E_FAIL :*/ S_OK; |
|
2994 } |
|
2995 |
|
2996 //**** IPersistFile |
|
2997 /* |
|
2998 */ |
|
2999 HRESULT WINAPI QAxServerBase::SaveCompleted(LPCOLESTR fileName) |
|
3000 { |
|
3001 if (qt.object->metaObject()->indexOfClassInfo("MIME") == -1) |
|
3002 return E_NOTIMPL; |
|
3003 |
|
3004 currentFileName = QString::fromWCharArray(fileName); |
|
3005 return S_OK; |
|
3006 } |
|
3007 |
|
3008 HRESULT WINAPI QAxServerBase::GetCurFile(LPOLESTR *currentFile) |
|
3009 { |
|
3010 if (qt.object->metaObject()->indexOfClassInfo("MIME") == -1) |
|
3011 return E_NOTIMPL; |
|
3012 |
|
3013 if (currentFileName.isEmpty()) { |
|
3014 *currentFile = 0; |
|
3015 return S_FALSE; |
|
3016 } |
|
3017 IMalloc *malloc = 0; |
|
3018 CoGetMalloc(1, &malloc); |
|
3019 if (!malloc) |
|
3020 return E_OUTOFMEMORY; |
|
3021 |
|
3022 *currentFile = static_cast<wchar_t *>(malloc->Alloc(currentFileName.length() * 2)); |
|
3023 malloc->Release(); |
|
3024 memcpy(*currentFile, currentFileName.unicode(), currentFileName.length() * 2); |
|
3025 |
|
3026 return S_OK; |
|
3027 } |
|
3028 |
|
3029 HRESULT WINAPI QAxServerBase::Load(LPCOLESTR fileName, DWORD mode) |
|
3030 { |
|
3031 const QMetaObject *mo = qt.object->metaObject(); |
|
3032 int mimeIndex = mo->indexOfClassInfo("MIME"); |
|
3033 if (mimeIndex == -1) |
|
3034 return E_NOTIMPL; |
|
3035 |
|
3036 QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable"); |
|
3037 if (!axb) { |
|
3038 qWarning() << class_name << ": No QAxBindable implementation for mime-type handling"; |
|
3039 return E_NOTIMPL; |
|
3040 } |
|
3041 |
|
3042 QString loadFileName = QString::fromWCharArray(fileName); |
|
3043 QString fileExtension = loadFileName.mid(loadFileName.lastIndexOf(QLatin1Char('.')) + 1); |
|
3044 QFile file(loadFileName); |
|
3045 |
|
3046 QString mimeType = QLatin1String(mo->classInfo(mimeIndex).value()); |
|
3047 QStringList mimeTypes = mimeType.split(QLatin1Char(';')); |
|
3048 for (int m = 0; m < mimeTypes.count(); ++m) { |
|
3049 QString mime = mimeTypes.at(m); |
|
3050 if (mime.count(QLatin1Char(':')) != 2) { |
|
3051 qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME"; |
|
3052 continue; |
|
3053 } |
|
3054 |
|
3055 mimeType = mime.left(mimeType.indexOf(QLatin1Char(':'))); // first type |
|
3056 if (mimeType.isEmpty()) { |
|
3057 qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME"; |
|
3058 continue; |
|
3059 } |
|
3060 QString mimeExtension = mime.mid(mimeType.length() + 1); |
|
3061 mimeExtension = mimeExtension.left(mimeExtension.indexOf(QLatin1Char(':'))); |
|
3062 if (mimeExtension != fileExtension) |
|
3063 continue; |
|
3064 |
|
3065 if (axb->readData(&file, mimeType)) { |
|
3066 currentFileName = loadFileName; |
|
3067 return S_OK; |
|
3068 } |
|
3069 } |
|
3070 |
|
3071 return E_FAIL; |
|
3072 } |
|
3073 |
|
3074 HRESULT WINAPI QAxServerBase::Save(LPCOLESTR fileName, BOOL fRemember) |
|
3075 { |
|
3076 const QMetaObject *mo = qt.object->metaObject(); |
|
3077 int mimeIndex = mo->indexOfClassInfo("MIME"); |
|
3078 if (mimeIndex == -1) |
|
3079 return E_NOTIMPL; |
|
3080 |
|
3081 QAxBindable *axb = (QAxBindable*)qt.object->qt_metacast("QAxBindable"); |
|
3082 if (!axb) { |
|
3083 qWarning() << class_name << ": No QAxBindable implementation for mime-type handling"; |
|
3084 return E_NOTIMPL; |
|
3085 } |
|
3086 |
|
3087 QString saveFileName = QString::fromWCharArray(fileName); |
|
3088 QString fileExtension = saveFileName.mid(saveFileName.lastIndexOf(QLatin1Char('.')) + 1); |
|
3089 QFile file(saveFileName); |
|
3090 |
|
3091 QString mimeType = QLatin1String(mo->classInfo(mimeIndex).value()); |
|
3092 QStringList mimeTypes = mimeType.split(QLatin1Char(';')); |
|
3093 for (int m = 0; m < mimeTypes.count(); ++m) { |
|
3094 QString mime = mimeTypes.at(m); |
|
3095 if (mime.count(QLatin1Char(':')) != 2) { |
|
3096 qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME"; |
|
3097 continue; |
|
3098 } |
|
3099 mimeType = mime.left(mimeType.indexOf(QLatin1Char(':'))); // first type |
|
3100 if (mimeType.isEmpty()) { |
|
3101 qWarning() << class_name << ": Invalid syntax in Q_CLASSINFO for MIME"; |
|
3102 continue; |
|
3103 } |
|
3104 QString mimeExtension = mime.mid(mimeType.length() + 1); |
|
3105 mimeExtension = mimeExtension.left(mimeExtension.indexOf(QLatin1Char(':'))); |
|
3106 if (mimeExtension != fileExtension) |
|
3107 continue; |
|
3108 if (axb->writeData(&file)) { |
|
3109 if (fRemember) |
|
3110 currentFileName = saveFileName; |
|
3111 return S_OK; |
|
3112 } |
|
3113 } |
|
3114 return E_FAIL; |
|
3115 } |
|
3116 |
|
3117 //**** IViewObject |
|
3118 /* |
|
3119 Draws the widget into the provided device context. |
|
3120 */ |
|
3121 HRESULT WINAPI QAxServerBase::Draw(DWORD dwAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, |
|
3122 HDC hicTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL /*lprcWBounds*/, |
|
3123 BOOL(__stdcall* /*pfnContinue*/)(ULONG_PTR), ULONG_PTR /*dwContinue*/) |
|
3124 { |
|
3125 if (!lprcBounds) |
|
3126 return E_INVALIDARG; |
|
3127 |
|
3128 internalCreate(); |
|
3129 if (!isWidget || !qt.widget) |
|
3130 return OLE_E_BLANK; |
|
3131 |
|
3132 switch (dwAspect) { |
|
3133 case DVASPECT_CONTENT: |
|
3134 case DVASPECT_OPAQUE: |
|
3135 case DVASPECT_TRANSPARENT: |
|
3136 break; |
|
3137 default: |
|
3138 return DV_E_DVASPECT; |
|
3139 } |
|
3140 if (!ptd) |
|
3141 hicTargetDev = 0; |
|
3142 |
|
3143 bool bDeleteDC = false; |
|
3144 if (!hicTargetDev) { |
|
3145 hicTargetDev = ::CreateDC(L"DISPLAY", NULL, NULL, NULL); |
|
3146 bDeleteDC = (hicTargetDev != hdcDraw); |
|
3147 } |
|
3148 |
|
3149 RECTL rc = *lprcBounds; |
|
3150 bool bMetaFile = GetDeviceCaps(hdcDraw, TECHNOLOGY) == DT_METAFILE; |
|
3151 if (!bMetaFile) |
|
3152 ::LPtoDP(hicTargetDev, (LPPOINT)&rc, 2); |
|
3153 |
|
3154 QPixmap pm = QPixmap::grabWidget(qt.widget); |
|
3155 HBITMAP hbm = pm.toWinHBITMAP(); |
|
3156 HDC hdc = CreateCompatibleDC(0); |
|
3157 SelectObject(hdc, hbm); |
|
3158 ::StretchBlt(hdcDraw, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hdc, 0, 0,pm.width(), pm.height(), SRCCOPY); |
|
3159 DeleteDC(hdc); |
|
3160 DeleteObject(hbm); |
|
3161 |
|
3162 if (bDeleteDC) |
|
3163 DeleteDC(hicTargetDev); |
|
3164 |
|
3165 return S_OK; |
|
3166 } |
|
3167 |
|
3168 /* |
|
3169 Not implemented. |
|
3170 */ |
|
3171 HRESULT WINAPI QAxServerBase::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, |
|
3172 HDC hicTargetDev, LOGPALETTE **ppColorSet) |
|
3173 { |
|
3174 return E_NOTIMPL; |
|
3175 } |
|
3176 |
|
3177 /* |
|
3178 Not implemented. |
|
3179 */ |
|
3180 HRESULT WINAPI QAxServerBase::Freeze(DWORD dwAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze) |
|
3181 { |
|
3182 return E_NOTIMPL; |
|
3183 } |
|
3184 |
|
3185 /* |
|
3186 Not implemented. |
|
3187 */ |
|
3188 HRESULT WINAPI QAxServerBase::Unfreeze(DWORD dwFreeze) |
|
3189 { |
|
3190 return E_NOTIMPL; |
|
3191 } |
|
3192 |
|
3193 /* |
|
3194 Stores the provided advise sink. |
|
3195 */ |
|
3196 HRESULT WINAPI QAxServerBase::SetAdvise(DWORD /*aspects*/, DWORD /*advf*/, IAdviseSink *pAdvSink) |
|
3197 { |
|
3198 if (m_spAdviseSink) m_spAdviseSink->Release(); |
|
3199 |
|
3200 m_spAdviseSink = pAdvSink; |
|
3201 if (m_spAdviseSink) m_spAdviseSink->AddRef(); |
|
3202 return S_OK; |
|
3203 } |
|
3204 |
|
3205 /* |
|
3206 Returns the advise sink. |
|
3207 */ |
|
3208 HRESULT WINAPI QAxServerBase::GetAdvise(DWORD* /*aspects*/, DWORD* /*advf*/, IAdviseSink **ppAdvSink) |
|
3209 { |
|
3210 if (!ppAdvSink) |
|
3211 return E_POINTER; |
|
3212 |
|
3213 *ppAdvSink = m_spAdviseSink; |
|
3214 if (*ppAdvSink) |
|
3215 (*ppAdvSink)->AddRef(); |
|
3216 return S_OK; |
|
3217 } |
|
3218 |
|
3219 //**** IViewObject2 |
|
3220 /* |
|
3221 Returns the current size ONLY if the widget has already been sized. |
|
3222 */ |
|
3223 HRESULT WINAPI QAxServerBase::GetExtent(DWORD dwAspect, LONG /*lindex*/, DVTARGETDEVICE* /*ptd*/, LPSIZEL lpsizel) |
|
3224 { |
|
3225 if (!isWidget || !qt.widget || !qt.widget->testAttribute(Qt::WA_Resized)) |
|
3226 return OLE_E_BLANK; |
|
3227 |
|
3228 return GetExtent(dwAspect, lpsizel); |
|
3229 } |
|
3230 |
|
3231 //**** IOleControl |
|
3232 /* |
|
3233 Not implemented. |
|
3234 */ |
|
3235 HRESULT WINAPI QAxServerBase::GetControlInfo(LPCONTROLINFO) |
|
3236 { |
|
3237 return E_NOTIMPL; |
|
3238 } |
|
3239 |
|
3240 /* |
|
3241 Turns event firing on and off. |
|
3242 */ |
|
3243 HRESULT WINAPI QAxServerBase::FreezeEvents(BOOL bFreeze) |
|
3244 { |
|
3245 // member of CComControl |
|
3246 if (bFreeze) |
|
3247 freezeEvents++; |
|
3248 else |
|
3249 freezeEvents--; |
|
3250 |
|
3251 return S_OK; |
|
3252 } |
|
3253 |
|
3254 /* |
|
3255 Not implemented. |
|
3256 */ |
|
3257 HRESULT WINAPI QAxServerBase::OnMnemonic(LPMSG) |
|
3258 { |
|
3259 return E_NOTIMPL; |
|
3260 } |
|
3261 |
|
3262 /* |
|
3263 Update the ambient properties of the Qt widget. |
|
3264 */ |
|
3265 HRESULT WINAPI QAxServerBase::OnAmbientPropertyChange(DISPID dispID) |
|
3266 { |
|
3267 if (!m_spClientSite || !theObject) |
|
3268 return S_OK; |
|
3269 |
|
3270 IDispatch *disp = 0; |
|
3271 m_spClientSite->QueryInterface(IID_IDispatch, (void**)&disp); |
|
3272 if (!disp) |
|
3273 return S_OK; |
|
3274 |
|
3275 VARIANT var; |
|
3276 VariantInit(&var); |
|
3277 DISPPARAMS params = { 0, 0, 0, 0 }; |
|
3278 disp->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, ¶ms, &var, 0, 0); |
|
3279 disp->Release(); |
|
3280 disp = 0; |
|
3281 |
|
3282 switch(dispID) { |
|
3283 case DISPID_AMBIENT_APPEARANCE: |
|
3284 break; |
|
3285 case DISPID_AMBIENT_AUTOCLIP: |
|
3286 break; |
|
3287 case DISPID_AMBIENT_BACKCOLOR: |
|
3288 case DISPID_AMBIENT_FORECOLOR: |
|
3289 if (isWidget) { |
|
3290 long rgb; |
|
3291 if (var.vt == VT_UI4) |
|
3292 rgb = var.ulVal; |
|
3293 else if (var.vt == VT_I4) |
|
3294 rgb = var.lVal; |
|
3295 else |
|
3296 break; |
|
3297 QPalette pal = qt.widget->palette(); |
|
3298 pal.setColor(dispID == DISPID_AMBIENT_BACKCOLOR ? QPalette::Window : QPalette::WindowText, |
|
3299 OLEColorToQColor(rgb)); |
|
3300 qt.widget->setPalette(pal); |
|
3301 } |
|
3302 break; |
|
3303 case DISPID_AMBIENT_DISPLAYASDEFAULT: |
|
3304 break; |
|
3305 case DISPID_AMBIENT_DISPLAYNAME: |
|
3306 if (var.vt != VT_BSTR || !isWidget) |
|
3307 break; |
|
3308 qt.widget->setWindowTitle(QString::fromWCharArray(var.bstrVal)); |
|
3309 break; |
|
3310 case DISPID_AMBIENT_FONT: |
|
3311 if (var.vt != VT_DISPATCH || !isWidget) |
|
3312 break; |
|
3313 { |
|
3314 QVariant qvar = VARIANTToQVariant(var, "QFont", QVariant::Font); |
|
3315 QFont qfont = qVariantValue<QFont>(qvar); |
|
3316 qt.widget->setFont(qfont); |
|
3317 } |
|
3318 break; |
|
3319 case DISPID_AMBIENT_LOCALEID: |
|
3320 break; |
|
3321 case DISPID_AMBIENT_MESSAGEREFLECT: |
|
3322 if (var.vt != VT_BOOL) |
|
3323 break; |
|
3324 if (var.boolVal) |
|
3325 qt.widget->installEventFilter(this); |
|
3326 else |
|
3327 qt.widget->removeEventFilter(this); |
|
3328 break; |
|
3329 case DISPID_AMBIENT_PALETTE: |
|
3330 break; |
|
3331 case DISPID_AMBIENT_SCALEUNITS: |
|
3332 break; |
|
3333 case DISPID_AMBIENT_SHOWGRABHANDLES: |
|
3334 break; |
|
3335 case DISPID_AMBIENT_SHOWHATCHING: |
|
3336 break; |
|
3337 case DISPID_AMBIENT_SUPPORTSMNEMONICS: |
|
3338 break; |
|
3339 case DISPID_AMBIENT_TEXTALIGN: |
|
3340 break; |
|
3341 case DISPID_AMBIENT_UIDEAD: |
|
3342 if (var.vt != VT_BOOL || !isWidget) |
|
3343 break; |
|
3344 qt.widget->setEnabled(!var.boolVal); |
|
3345 break; |
|
3346 case DISPID_AMBIENT_USERMODE: |
|
3347 if (var.vt != VT_BOOL) |
|
3348 break; |
|
3349 inDesignMode = !var.boolVal; |
|
3350 break; |
|
3351 case DISPID_AMBIENT_RIGHTTOLEFT: |
|
3352 if (var.vt != VT_BOOL) |
|
3353 break; |
|
3354 qApp->setLayoutDirection(var.boolVal?Qt::RightToLeft:Qt::LeftToRight); |
|
3355 break; |
|
3356 } |
|
3357 |
|
3358 return S_OK; |
|
3359 } |
|
3360 |
|
3361 //**** IOleWindow |
|
3362 /* |
|
3363 Returns the HWND of the control. |
|
3364 */ |
|
3365 HRESULT WINAPI QAxServerBase::GetWindow(HWND *pHwnd) |
|
3366 { |
|
3367 if (!pHwnd) |
|
3368 return E_POINTER; |
|
3369 *pHwnd = m_hWnd; |
|
3370 return S_OK; |
|
3371 } |
|
3372 |
|
3373 /* |
|
3374 Enters What's This mode. |
|
3375 */ |
|
3376 HRESULT WINAPI QAxServerBase::ContextSensitiveHelp(BOOL fEnterMode) |
|
3377 { |
|
3378 if (fEnterMode) |
|
3379 QWhatsThis::enterWhatsThisMode(); |
|
3380 else |
|
3381 QWhatsThis::leaveWhatsThisMode(); |
|
3382 return S_OK; |
|
3383 } |
|
3384 |
|
3385 //**** IOleInPlaceObject |
|
3386 /* |
|
3387 Deactivates the control in place. |
|
3388 */ |
|
3389 HRESULT WINAPI QAxServerBase::InPlaceDeactivate() |
|
3390 { |
|
3391 if (!isInPlaceActive) |
|
3392 return S_OK; |
|
3393 UIDeactivate(); |
|
3394 |
|
3395 isInPlaceActive = false; |
|
3396 |
|
3397 // if we have a window, tell it to go away. |
|
3398 if (m_hWnd) { |
|
3399 if (::IsWindow(m_hWnd)) |
|
3400 ::DestroyWindow(m_hWnd); |
|
3401 m_hWnd = 0; |
|
3402 } |
|
3403 |
|
3404 if (m_spInPlaceSite) |
|
3405 m_spInPlaceSite->OnInPlaceDeactivate(); |
|
3406 |
|
3407 return S_OK; |
|
3408 } |
|
3409 |
|
3410 /* |
|
3411 Deactivates the control's user interface. |
|
3412 */ |
|
3413 HRESULT WINAPI QAxServerBase::UIDeactivate() |
|
3414 { |
|
3415 // if we're not UIActive, not much to do. |
|
3416 if (!isUIActive || !m_spInPlaceSite) |
|
3417 return S_OK; |
|
3418 |
|
3419 isUIActive = false; |
|
3420 |
|
3421 // notify frame windows, if appropriate, that we're no longer ui-active. |
|
3422 HWND hwndParent; |
|
3423 if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK) { |
|
3424 if (m_spInPlaceFrame) m_spInPlaceFrame->Release(); |
|
3425 m_spInPlaceFrame = 0; |
|
3426 IOleInPlaceUIWindow *spInPlaceUIWindow = 0; |
|
3427 RECT rcPos, rcClip; |
|
3428 OLEINPLACEFRAMEINFO frameInfo; |
|
3429 frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); |
|
3430 |
|
3431 m_spInPlaceSite->GetWindowContext(&m_spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo); |
|
3432 if (spInPlaceUIWindow) { |
|
3433 spInPlaceUIWindow->SetActiveObject(0, 0); |
|
3434 spInPlaceUIWindow->Release(); |
|
3435 } |
|
3436 if (m_spInPlaceFrame) { |
|
3437 removeMenu(); |
|
3438 if (menuBar) { |
|
3439 menuBar->removeEventFilter(this); |
|
3440 menuBar = 0; |
|
3441 } |
|
3442 if (statusBar) { |
|
3443 statusBar->removeEventFilter(this); |
|
3444 const int index = statusBar->metaObject()->indexOfSignal("messageChanged(QString)"); |
|
3445 QMetaObject::disconnect(statusBar, index, this, -1); |
|
3446 statusBar = 0; |
|
3447 } |
|
3448 m_spInPlaceFrame->SetActiveObject(0, 0); |
|
3449 m_spInPlaceFrame->Release(); |
|
3450 m_spInPlaceFrame = 0; |
|
3451 } |
|
3452 } |
|
3453 // we don't need to explicitly release the focus here since somebody |
|
3454 // else grabbing the focus is usually why we are getting called at all |
|
3455 m_spInPlaceSite->OnUIDeactivate(false); |
|
3456 |
|
3457 return S_OK; |
|
3458 } |
|
3459 |
|
3460 /* |
|
3461 Positions the control, and applies requested clipping. |
|
3462 */ |
|
3463 HRESULT WINAPI QAxServerBase::SetObjectRects(LPCRECT prcPos, LPCRECT prcClip) |
|
3464 { |
|
3465 if (prcPos == 0 || prcClip == 0) |
|
3466 return E_POINTER; |
|
3467 |
|
3468 if (m_hWnd) { |
|
3469 // the container wants us to clip, so figure out if we really need to |
|
3470 RECT rcIXect; |
|
3471 BOOL b = IntersectRect(&rcIXect, prcPos, prcClip); |
|
3472 HRGN tempRgn = 0; |
|
3473 if (b && !EqualRect(&rcIXect, prcPos)) { |
|
3474 OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top)); |
|
3475 tempRgn = CreateRectRgnIndirect(&rcIXect); |
|
3476 } |
|
3477 |
|
3478 ::SetWindowRgn(m_hWnd, tempRgn, true); |
|
3479 ::SetWindowPos(m_hWnd, 0, prcPos->left, prcPos->top, |
|
3480 prcPos->right - prcPos->left, prcPos->bottom - prcPos->top, |
|
3481 SWP_NOZORDER | SWP_NOACTIVATE); |
|
3482 } |
|
3483 |
|
3484 //Save the new extent. |
|
3485 m_currentExtent.rwidth() = qBound(qt.widget->minimumWidth(), int(prcPos->right - prcPos->left), qt.widget->maximumWidth()); |
|
3486 m_currentExtent.rheight() = qBound(qt.widget->minimumHeight(), int(prcPos->bottom - prcPos->top), qt.widget->maximumHeight()); |
|
3487 |
|
3488 return S_OK; |
|
3489 } |
|
3490 |
|
3491 /* |
|
3492 Not implemented. |
|
3493 */ |
|
3494 HRESULT WINAPI QAxServerBase::ReactivateAndUndo() |
|
3495 { |
|
3496 return E_NOTIMPL; |
|
3497 } |
|
3498 |
|
3499 //**** IOleInPlaceActiveObject |
|
3500 |
|
3501 Q_GUI_EXPORT int qt_translateKeyCode(int); |
|
3502 |
|
3503 HRESULT WINAPI QAxServerBase::TranslateAcceleratorW(MSG *pMsg) |
|
3504 { |
|
3505 if (pMsg->message != WM_KEYDOWN || !isWidget) |
|
3506 return S_FALSE; |
|
3507 |
|
3508 DWORD dwKeyMod = 0; |
|
3509 if (::GetKeyState(VK_SHIFT) < 0) |
|
3510 dwKeyMod |= 1; // KEYMOD_SHIFT |
|
3511 if (::GetKeyState(VK_CONTROL) < 0) |
|
3512 dwKeyMod |= 2; // KEYMOD_CONTROL |
|
3513 if (::GetKeyState(VK_MENU) < 0) |
|
3514 dwKeyMod |= 4; // KEYMOD_ALT |
|
3515 |
|
3516 switch (LOWORD(pMsg->wParam)) { |
|
3517 case VK_TAB: |
|
3518 if (isUIActive) { |
|
3519 bool shift = ::GetKeyState(VK_SHIFT) < 0; |
|
3520 bool giveUp = true; |
|
3521 QWidget *curFocus = qt.widget->focusWidget(); |
|
3522 if (curFocus) { |
|
3523 if (shift) { |
|
3524 if (!curFocus->isWindow()) { |
|
3525 QWidget *nextFocus = curFocus->nextInFocusChain(); |
|
3526 QWidget *prevFocus = 0; |
|
3527 QWidget *topLevel = 0; |
|
3528 while (nextFocus != curFocus) { |
|
3529 if (nextFocus->focusPolicy() & Qt::TabFocus) { |
|
3530 prevFocus = nextFocus; |
|
3531 topLevel = 0; |
|
3532 } else if (nextFocus->isWindow()) { |
|
3533 topLevel = nextFocus; |
|
3534 } |
|
3535 nextFocus = nextFocus->nextInFocusChain(); |
|
3536 } |
|
3537 |
|
3538 if (!topLevel) { |
|
3539 giveUp = false; |
|
3540 ((HackWidget*)curFocus)->focusNextPrevChild(false); |
|
3541 curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange); |
|
3542 } |
|
3543 } |
|
3544 } else { |
|
3545 QWidget *nextFocus = curFocus; |
|
3546 while (1) { |
|
3547 nextFocus = nextFocus->nextInFocusChain(); |
|
3548 if (nextFocus->isWindow()) |
|
3549 break; |
|
3550 if (nextFocus->focusPolicy() & Qt::TabFocus) { |
|
3551 giveUp = false; |
|
3552 ((HackWidget*)curFocus)->focusNextPrevChild(true); |
|
3553 curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange); |
|
3554 break; |
|
3555 } |
|
3556 } |
|
3557 } |
|
3558 } |
|
3559 if (giveUp) { |
|
3560 HWND hwnd = ::GetParent(m_hWnd); |
|
3561 ::SetFocus(hwnd); |
|
3562 } else { |
|
3563 return S_OK; |
|
3564 } |
|
3565 |
|
3566 } |
|
3567 break; |
|
3568 |
|
3569 case VK_LEFT: |
|
3570 case VK_RIGHT: |
|
3571 case VK_UP: |
|
3572 case VK_DOWN: |
|
3573 if (isUIActive) |
|
3574 return S_FALSE; |
|
3575 break; |
|
3576 |
|
3577 default: |
|
3578 if (isUIActive && qt.widget->focusWidget()) { |
|
3579 int state = Qt::NoButton; |
|
3580 if (dwKeyMod & 1) |
|
3581 state |= Qt::ShiftModifier; |
|
3582 if (dwKeyMod & 2) |
|
3583 state |= Qt::ControlModifier; |
|
3584 if (dwKeyMod & 4) |
|
3585 state |= Qt::AltModifier; |
|
3586 |
|
3587 int key = pMsg->wParam; |
|
3588 if (!(key >= 'A' && key <= 'Z') && !(key >= '0' && key <= '9')) |
|
3589 key = qt_translateKeyCode(pMsg->wParam); |
|
3590 |
|
3591 QKeyEvent override(QEvent::ShortcutOverride, key, (Qt::KeyboardModifiers)state); |
|
3592 override.ignore(); |
|
3593 QApplication::sendEvent(qt.widget->focusWidget(), &override); |
|
3594 if (override.isAccepted()) |
|
3595 return S_FALSE; |
|
3596 } |
|
3597 break; |
|
3598 } |
|
3599 |
|
3600 if (!m_spClientSite) |
|
3601 return S_FALSE; |
|
3602 |
|
3603 IOleControlSite *controlSite = 0; |
|
3604 m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&controlSite); |
|
3605 if (!controlSite) |
|
3606 return S_FALSE; |
|
3607 bool resetUserData = false; |
|
3608 // set server type in the user-data of the window. |
|
3609 #ifdef GWLP_USERDATA |
|
3610 LONG_PTR serverType = QAX_INPROC_SERVER; |
|
3611 #else |
|
3612 LONG serverType = QAX_INPROC_SERVER; |
|
3613 #endif |
|
3614 if (qAxOutProcServer) |
|
3615 serverType = QAX_OUTPROC_SERVER; |
|
3616 #ifdef GWLP_USERDATA |
|
3617 LONG_PTR oldData = SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, serverType); |
|
3618 #else |
|
3619 LONG oldData = SetWindowLong(pMsg->hwnd, GWL_USERDATA, serverType); |
|
3620 #endif |
|
3621 HRESULT hres = controlSite->TranslateAcceleratorW(pMsg, dwKeyMod); |
|
3622 controlSite->Release(); |
|
3623 // reset the user-data for the window. |
|
3624 #ifdef GWLP_USERDATA |
|
3625 SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, oldData); |
|
3626 #else |
|
3627 SetWindowLong(pMsg->hwnd, GWL_USERDATA, oldData); |
|
3628 #endif |
|
3629 return hres; |
|
3630 } |
|
3631 |
|
3632 HRESULT WINAPI QAxServerBase::TranslateAcceleratorA(MSG *pMsg) |
|
3633 { |
|
3634 return TranslateAcceleratorW(pMsg); |
|
3635 } |
|
3636 |
|
3637 HRESULT WINAPI QAxServerBase::OnFrameWindowActivate(BOOL fActivate) |
|
3638 { |
|
3639 if (fActivate) { |
|
3640 if (wasUIActive) |
|
3641 ::SetFocus(m_hWnd); |
|
3642 } else { |
|
3643 wasUIActive = isUIActive; |
|
3644 } |
|
3645 return S_OK; |
|
3646 } |
|
3647 |
|
3648 HRESULT WINAPI QAxServerBase::OnDocWindowActivate(BOOL fActivate) |
|
3649 { |
|
3650 return S_OK; |
|
3651 } |
|
3652 |
|
3653 HRESULT WINAPI QAxServerBase::ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fFrameWindow) |
|
3654 { |
|
3655 return S_OK; |
|
3656 } |
|
3657 |
|
3658 HRESULT WINAPI QAxServerBase::EnableModeless(BOOL fEnable) |
|
3659 { |
|
3660 if (!isWidget) |
|
3661 return S_OK; |
|
3662 |
|
3663 EnableWindow(qt.widget->winId(), fEnable); |
|
3664 return S_OK; |
|
3665 } |
|
3666 |
|
3667 //**** IOleObject |
|
3668 |
|
3669 static inline LPOLESTR QStringToOLESTR(const QString &qstring) |
|
3670 { |
|
3671 LPOLESTR olestr = (wchar_t*)CoTaskMemAlloc(qstring.length()*2+2); |
|
3672 memcpy(olestr, (ushort*)qstring.unicode(), qstring.length()*2); |
|
3673 olestr[qstring.length()] = 0; |
|
3674 return olestr; |
|
3675 } |
|
3676 |
|
3677 /* |
|
3678 \reimp |
|
3679 |
|
3680 See documentation of IOleObject::GetUserType. |
|
3681 */ |
|
3682 HRESULT WINAPI QAxServerBase::GetUserType(DWORD dwFormOfType, LPOLESTR *pszUserType) |
|
3683 { |
|
3684 if (!pszUserType) |
|
3685 return E_POINTER; |
|
3686 |
|
3687 switch (dwFormOfType) { |
|
3688 case USERCLASSTYPE_FULL: |
|
3689 *pszUserType = QStringToOLESTR(class_name); |
|
3690 break; |
|
3691 case USERCLASSTYPE_SHORT: |
|
3692 if (!qt.widget || !isWidget || qt.widget->windowTitle().isEmpty()) |
|
3693 *pszUserType = QStringToOLESTR(class_name); |
|
3694 else |
|
3695 *pszUserType = QStringToOLESTR(qt.widget->windowTitle()); |
|
3696 break; |
|
3697 case USERCLASSTYPE_APPNAME: |
|
3698 *pszUserType = QStringToOLESTR(qApp->objectName()); |
|
3699 break; |
|
3700 } |
|
3701 |
|
3702 return S_OK; |
|
3703 } |
|
3704 |
|
3705 /* |
|
3706 Returns the status flags registered for this control. |
|
3707 */ |
|
3708 HRESULT WINAPI QAxServerBase::GetMiscStatus(DWORD dwAspect, DWORD *pdwStatus) |
|
3709 { |
|
3710 return OleRegGetMiscStatus(qAxFactory()->classID(class_name), dwAspect, pdwStatus); |
|
3711 } |
|
3712 |
|
3713 /* |
|
3714 Stores the provided advise sink. |
|
3715 */ |
|
3716 HRESULT WINAPI QAxServerBase::Advise(IAdviseSink* pAdvSink, DWORD* pdwConnection) |
|
3717 { |
|
3718 *pdwConnection = adviseSinks.count() + 1; |
|
3719 STATDATA data = { {0, 0, DVASPECT_CONTENT, -1, TYMED_NULL} , 0, pAdvSink, *pdwConnection }; |
|
3720 adviseSinks.append(data); |
|
3721 pAdvSink->AddRef(); |
|
3722 return S_OK; |
|
3723 } |
|
3724 |
|
3725 /* |
|
3726 Closes the control. |
|
3727 */ |
|
3728 HRESULT WINAPI QAxServerBase::Close(DWORD dwSaveOption) |
|
3729 { |
|
3730 if (dwSaveOption != OLECLOSE_NOSAVE && m_spClientSite) |
|
3731 m_spClientSite->SaveObject(); |
|
3732 if (isInPlaceActive) { |
|
3733 HRESULT hr = InPlaceDeactivate(); |
|
3734 if (FAILED(hr)) |
|
3735 return hr; |
|
3736 } |
|
3737 if (m_hWnd) { |
|
3738 if (IsWindow(m_hWnd)) |
|
3739 DestroyWindow(m_hWnd); |
|
3740 m_hWnd = 0; |
|
3741 if (m_spClientSite) |
|
3742 m_spClientSite->OnShowWindow(false); |
|
3743 } |
|
3744 |
|
3745 if (m_spInPlaceSite) m_spInPlaceSite->Release(); |
|
3746 m_spInPlaceSite = 0; |
|
3747 |
|
3748 if (m_spAdviseSink) |
|
3749 m_spAdviseSink->OnClose(); |
|
3750 for (int i = 0; i < adviseSinks.count(); ++i) { |
|
3751 adviseSinks.at(i).pAdvSink->OnClose(); |
|
3752 } |
|
3753 |
|
3754 return S_OK; |
|
3755 } |
|
3756 |
|
3757 bool qax_disable_inplaceframe = true; |
|
3758 |
|
3759 /* |
|
3760 Executes the steps to activate the control. |
|
3761 */ |
|
3762 HRESULT QAxServerBase::internalActivate() |
|
3763 { |
|
3764 if (!m_spClientSite) |
|
3765 return S_OK; |
|
3766 if (!m_spInPlaceSite) |
|
3767 m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void**)&m_spInPlaceSite); |
|
3768 if (!m_spInPlaceSite) |
|
3769 return E_FAIL; |
|
3770 |
|
3771 HRESULT hr = E_FAIL; |
|
3772 if (!isInPlaceActive) { |
|
3773 BOOL bNoRedraw = false; |
|
3774 hr = m_spInPlaceSite->CanInPlaceActivate(); |
|
3775 if (FAILED(hr)) |
|
3776 return hr; |
|
3777 if (hr != S_OK) |
|
3778 return E_FAIL; |
|
3779 m_spInPlaceSite->OnInPlaceActivate(); |
|
3780 } |
|
3781 |
|
3782 isInPlaceActive = true; |
|
3783 OnAmbientPropertyChange(DISPID_AMBIENT_USERMODE); |
|
3784 |
|
3785 if (isWidget) { |
|
3786 IOleInPlaceUIWindow *spInPlaceUIWindow = 0; |
|
3787 HWND hwndParent; |
|
3788 if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK) { |
|
3789 // get location in the parent window, as well as some information about the parent |
|
3790 if (m_spInPlaceFrame) m_spInPlaceFrame->Release(); |
|
3791 m_spInPlaceFrame = 0; |
|
3792 RECT rcPos, rcClip; |
|
3793 OLEINPLACEFRAMEINFO frameInfo; |
|
3794 frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); |
|
3795 m_spInPlaceSite->GetWindowContext(&m_spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo); |
|
3796 if (m_hWnd) { |
|
3797 ::ShowWindow(m_hWnd, SW_SHOW); |
|
3798 if (!::IsChild(m_hWnd, ::GetFocus()) && qt.widget->focusPolicy() != Qt::NoFocus) |
|
3799 ::SetFocus(m_hWnd); |
|
3800 } else { |
|
3801 create(hwndParent, rcPos); |
|
3802 } |
|
3803 } |
|
3804 |
|
3805 // Gone active by now, take care of UIACTIVATE |
|
3806 canTakeFocus = qt.widget->focusPolicy() != Qt::NoFocus && !inDesignMode; |
|
3807 if (!canTakeFocus && !inDesignMode) { |
|
3808 QList<QWidget*> widgets = qFindChildren<QWidget*>(qt.widget); |
|
3809 for (int w = 0; w < widgets.count(); ++w) { |
|
3810 QWidget *widget = widgets[w]; |
|
3811 canTakeFocus = widget->focusPolicy() != Qt::NoFocus; |
|
3812 if (canTakeFocus) |
|
3813 break; |
|
3814 } |
|
3815 } |
|
3816 if (!isUIActive && canTakeFocus) { |
|
3817 isUIActive = true; |
|
3818 hr = m_spInPlaceSite->OnUIActivate(); |
|
3819 if (FAILED(hr)) { |
|
3820 if (m_spInPlaceFrame) m_spInPlaceFrame->Release(); |
|
3821 m_spInPlaceFrame = 0; |
|
3822 if (spInPlaceUIWindow) spInPlaceUIWindow->Release(); |
|
3823 return hr; |
|
3824 } |
|
3825 |
|
3826 if (isInPlaceActive) { |
|
3827 if (!::IsChild(m_hWnd, ::GetFocus())) |
|
3828 ::SetFocus(m_hWnd); |
|
3829 } |
|
3830 |
|
3831 if (m_spInPlaceFrame) { |
|
3832 hr = m_spInPlaceFrame->SetActiveObject(this, QStringToBSTR(class_name)); |
|
3833 if (!FAILED(hr)) { |
|
3834 menuBar = (qt.widget && !qax_disable_inplaceframe) ? qFindChild<QMenuBar*>(qt.widget) : 0; |
|
3835 if (menuBar && !menuBar->isVisible()) { |
|
3836 createMenu(menuBar); |
|
3837 menuBar->hide(); |
|
3838 menuBar->installEventFilter(this); |
|
3839 } |
|
3840 statusBar = qt.widget ? qFindChild<QStatusBar*>(qt.widget) : 0; |
|
3841 if (statusBar && !statusBar->isVisible()) { |
|
3842 const int index = statusBar->metaObject()->indexOfSignal("messageChanged(QString)"); |
|
3843 QMetaObject::connect(statusBar, index, this, -1); |
|
3844 statusBar->hide(); |
|
3845 statusBar->installEventFilter(this); |
|
3846 } |
|
3847 } |
|
3848 } |
|
3849 if (spInPlaceUIWindow) { |
|
3850 spInPlaceUIWindow->SetActiveObject(this, QStringToBSTR(class_name)); |
|
3851 spInPlaceUIWindow->SetBorderSpace(0); |
|
3852 } |
|
3853 } |
|
3854 if (spInPlaceUIWindow) spInPlaceUIWindow->Release(); |
|
3855 ShowWindow(m_hWnd, SW_NORMAL); |
|
3856 } |
|
3857 |
|
3858 m_spClientSite->ShowObject(); |
|
3859 |
|
3860 return S_OK; |
|
3861 } |
|
3862 |
|
3863 /* |
|
3864 Executes the "verb" \a iVerb. |
|
3865 */ |
|
3866 HRESULT WINAPI QAxServerBase::DoVerb(LONG iVerb, LPMSG /*lpmsg*/, IOleClientSite* /*pActiveSite*/, LONG /*lindex*/, |
|
3867 HWND /*hwndParent*/, LPCRECT /*prcPosRect*/) |
|
3868 { |
|
3869 HRESULT hr = E_NOTIMPL; |
|
3870 switch (iVerb) |
|
3871 { |
|
3872 case OLEIVERB_SHOW: |
|
3873 hr = internalActivate(); |
|
3874 if (SUCCEEDED(hr)) |
|
3875 hr = S_OK; |
|
3876 break; |
|
3877 |
|
3878 case OLEIVERB_PRIMARY: |
|
3879 case OLEIVERB_INPLACEACTIVATE: |
|
3880 hr = internalActivate(); |
|
3881 if (SUCCEEDED(hr)) { |
|
3882 hr = S_OK; |
|
3883 update(); |
|
3884 } |
|
3885 break; |
|
3886 |
|
3887 case OLEIVERB_UIACTIVATE: |
|
3888 if (!isUIActive) { |
|
3889 hr = internalActivate(); |
|
3890 if (SUCCEEDED(hr)) |
|
3891 hr = S_OK; |
|
3892 } |
|
3893 break; |
|
3894 |
|
3895 case OLEIVERB_HIDE: |
|
3896 UIDeactivate(); |
|
3897 if (m_hWnd) |
|
3898 ::ShowWindow(m_hWnd, SW_HIDE); |
|
3899 hr = S_OK; |
|
3900 return hr; |
|
3901 |
|
3902 default: |
|
3903 break; |
|
3904 } |
|
3905 return hr; |
|
3906 } |
|
3907 |
|
3908 /* |
|
3909 Not implemented. |
|
3910 */ |
|
3911 HRESULT WINAPI QAxServerBase::EnumAdvise(IEnumSTATDATA** /*ppenumAdvise*/) |
|
3912 { |
|
3913 return E_NOTIMPL; |
|
3914 } |
|
3915 |
|
3916 /* |
|
3917 Returns an enumerator for the verbs registered for this class. |
|
3918 */ |
|
3919 HRESULT WINAPI QAxServerBase::EnumVerbs(IEnumOLEVERB** ppEnumOleVerb) |
|
3920 { |
|
3921 if (!ppEnumOleVerb) |
|
3922 return E_POINTER; |
|
3923 return OleRegEnumVerbs(qAxFactory()->classID(class_name), ppEnumOleVerb); |
|
3924 } |
|
3925 |
|
3926 /* |
|
3927 Returns the current client site.. |
|
3928 */ |
|
3929 HRESULT WINAPI QAxServerBase::GetClientSite(IOleClientSite** ppClientSite) |
|
3930 { |
|
3931 if (!ppClientSite) |
|
3932 return E_POINTER; |
|
3933 *ppClientSite = m_spClientSite; |
|
3934 if (*ppClientSite) |
|
3935 (*ppClientSite)->AddRef(); |
|
3936 return S_OK; |
|
3937 } |
|
3938 |
|
3939 /* |
|
3940 Not implemented. |
|
3941 */ |
|
3942 HRESULT WINAPI QAxServerBase::GetClipboardData(DWORD, IDataObject**) |
|
3943 { |
|
3944 return E_NOTIMPL; |
|
3945 } |
|
3946 |
|
3947 /* |
|
3948 Returns the current extent. |
|
3949 */ |
|
3950 HRESULT WINAPI QAxServerBase::GetExtent(DWORD dwDrawAspect, SIZEL* psizel) |
|
3951 { |
|
3952 if (dwDrawAspect != DVASPECT_CONTENT || !isWidget || !qt.widget) |
|
3953 return E_FAIL; |
|
3954 if (!psizel) |
|
3955 return E_POINTER; |
|
3956 |
|
3957 psizel->cx = MAP_PIX_TO_LOGHIM(m_currentExtent.width(), qt.widget->logicalDpiX()); |
|
3958 psizel->cy = MAP_PIX_TO_LOGHIM(m_currentExtent.height(), qt.widget->logicalDpiY()); |
|
3959 return S_OK; |
|
3960 } |
|
3961 |
|
3962 /* |
|
3963 Not implemented. |
|
3964 */ |
|
3965 HRESULT WINAPI QAxServerBase::GetMoniker(DWORD, DWORD, IMoniker** ) |
|
3966 { |
|
3967 return E_NOTIMPL; |
|
3968 } |
|
3969 |
|
3970 /* |
|
3971 Returns the CLSID of this class. |
|
3972 */ |
|
3973 HRESULT WINAPI QAxServerBase::GetUserClassID(CLSID* pClsid) |
|
3974 { |
|
3975 if (!pClsid) |
|
3976 return E_POINTER; |
|
3977 *pClsid = qAxFactory()->classID(class_name); |
|
3978 return S_OK; |
|
3979 } |
|
3980 |
|
3981 /* |
|
3982 Not implemented. |
|
3983 */ |
|
3984 HRESULT WINAPI QAxServerBase::InitFromData(IDataObject*, BOOL, DWORD) |
|
3985 { |
|
3986 return E_NOTIMPL; |
|
3987 } |
|
3988 |
|
3989 /* |
|
3990 Not implemented. |
|
3991 */ |
|
3992 HRESULT WINAPI QAxServerBase::IsUpToDate() |
|
3993 { |
|
3994 return S_OK; |
|
3995 } |
|
3996 |
|
3997 /* |
|
3998 Stores the client site. |
|
3999 */ |
|
4000 HRESULT WINAPI QAxServerBase::SetClientSite(IOleClientSite* pClientSite) |
|
4001 { |
|
4002 // release all client site interfaces |
|
4003 if (m_spClientSite) m_spClientSite->Release(); |
|
4004 if (m_spInPlaceSite) m_spInPlaceSite->Release(); |
|
4005 m_spInPlaceSite = 0; |
|
4006 if (m_spInPlaceFrame) m_spInPlaceFrame->Release(); |
|
4007 m_spInPlaceFrame = 0; |
|
4008 |
|
4009 m_spClientSite = pClientSite; |
|
4010 if (m_spClientSite) { |
|
4011 m_spClientSite->AddRef(); |
|
4012 m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite); |
|
4013 } |
|
4014 |
|
4015 return S_OK; |
|
4016 } |
|
4017 |
|
4018 /* |
|
4019 Not implemented. |
|
4020 */ |
|
4021 HRESULT WINAPI QAxServerBase::SetColorScheme(LOGPALETTE*) |
|
4022 { |
|
4023 return E_NOTIMPL; |
|
4024 } |
|
4025 |
|
4026 |
|
4027 #ifdef QT_DLL // avoid conflict with symbol in static lib |
|
4028 bool qt_sendSpontaneousEvent(QObject *o, QEvent *e) |
|
4029 { |
|
4030 return QCoreApplication::sendSpontaneousEvent(o, e); |
|
4031 } |
|
4032 #endif |
|
4033 |
|
4034 /* |
|
4035 Tries to set the size of the control. |
|
4036 */ |
|
4037 HRESULT WINAPI QAxServerBase::SetExtent(DWORD dwDrawAspect, SIZEL* psizel) |
|
4038 { |
|
4039 if (dwDrawAspect != DVASPECT_CONTENT) |
|
4040 return DV_E_DVASPECT; |
|
4041 if (!psizel) |
|
4042 return E_POINTER; |
|
4043 |
|
4044 if (!isWidget || !qt.widget) // nothing to do |
|
4045 return S_OK; |
|
4046 |
|
4047 QSize proposedSize(MAP_LOGHIM_TO_PIX(psizel->cx, qt.widget->logicalDpiX()), |
|
4048 MAP_LOGHIM_TO_PIX(psizel->cy, qt.widget->logicalDpiY())); |
|
4049 |
|
4050 // can the widget be resized at all? |
|
4051 if (qt.widget->minimumSize() == qt.widget->maximumSize() && qt.widget->minimumSize() != proposedSize) |
|
4052 return E_FAIL; |
|
4053 //Save the extent, bound to the widget restrictions. |
|
4054 m_currentExtent.rwidth() = qBound(qt.widget->minimumWidth(), proposedSize.width(), qt.widget->maximumWidth()); |
|
4055 m_currentExtent.rheight() = qBound(qt.widget->minimumHeight(), proposedSize.height(), qt.widget->maximumHeight()); |
|
4056 |
|
4057 resize(proposedSize); |
|
4058 return S_OK; |
|
4059 } |
|
4060 |
|
4061 /* |
|
4062 Not implemented. |
|
4063 */ |
|
4064 HRESULT WINAPI QAxServerBase::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj) |
|
4065 { |
|
4066 return S_OK; |
|
4067 } |
|
4068 |
|
4069 /* |
|
4070 Not implemented. |
|
4071 */ |
|
4072 HRESULT WINAPI QAxServerBase::SetMoniker(DWORD, IMoniker*) |
|
4073 { |
|
4074 return E_NOTIMPL; |
|
4075 } |
|
4076 |
|
4077 /* |
|
4078 Disconnects an advise sink. |
|
4079 */ |
|
4080 HRESULT WINAPI QAxServerBase::Unadvise(DWORD dwConnection) |
|
4081 { |
|
4082 for (int i = 0; i < adviseSinks.count(); ++i) { |
|
4083 STATDATA entry = adviseSinks.at(i); |
|
4084 if (entry.dwConnection == dwConnection) { |
|
4085 entry.pAdvSink->Release(); |
|
4086 adviseSinks.removeAt(i); |
|
4087 return S_OK; |
|
4088 } |
|
4089 } |
|
4090 return OLE_E_NOCONNECTION; |
|
4091 } |
|
4092 |
|
4093 /* |
|
4094 Not implemented. |
|
4095 */ |
|
4096 HRESULT WINAPI QAxServerBase::Update() |
|
4097 { |
|
4098 return S_OK; |
|
4099 } |
|
4100 |
|
4101 //**** IDataObject |
|
4102 /* |
|
4103 Calls IViewObject::Draw after setting up the parameters. |
|
4104 */ |
|
4105 HRESULT WINAPI QAxServerBase::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium) |
|
4106 { |
|
4107 if (!pmedium) |
|
4108 return E_POINTER; |
|
4109 if ((pformatetcIn->tymed & TYMED_MFPICT) == 0) |
|
4110 return DATA_E_FORMATETC; |
|
4111 |
|
4112 internalCreate(); |
|
4113 if (!isWidget || !qt.widget) |
|
4114 return E_UNEXPECTED; |
|
4115 |
|
4116 // Container wants to draw, but the size is not defined yet - ask container |
|
4117 if (m_spInPlaceSite && !qt.widget->testAttribute(Qt::WA_Resized)) { |
|
4118 IOleInPlaceUIWindow *spInPlaceUIWindow = 0; |
|
4119 RECT rcPos, rcClip; |
|
4120 OLEINPLACEFRAMEINFO frameInfo; |
|
4121 frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); |
|
4122 |
|
4123 HRESULT hres = m_spInPlaceSite->GetWindowContext(&m_spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo); |
|
4124 if (hres == S_OK) { |
|
4125 QSize size(rcPos.right - rcPos.left, rcPos.bottom - rcPos.top); |
|
4126 resize(size); |
|
4127 } else { |
|
4128 qt.widget->adjustSize(); |
|
4129 } |
|
4130 if (spInPlaceUIWindow) spInPlaceUIWindow->Release(); // no need for it |
|
4131 } |
|
4132 |
|
4133 int width = qt.widget->width(); |
|
4134 int height = qt.widget->height(); |
|
4135 RECTL rectl = {0, 0, width, height}; |
|
4136 |
|
4137 HDC hdc = CreateMetaFile(0); |
|
4138 SaveDC(hdc); |
|
4139 SetWindowOrgEx(hdc, 0, 0, 0); |
|
4140 SetWindowExtEx(hdc, rectl.right, rectl.bottom, 0); |
|
4141 |
|
4142 Draw(pformatetcIn->dwAspect, pformatetcIn->lindex, 0, pformatetcIn->ptd, 0, hdc, &rectl, &rectl, 0, 0); |
|
4143 |
|
4144 RestoreDC(hdc, -1); |
|
4145 HMETAFILE hMF = CloseMetaFile(hdc); |
|
4146 if (!hMF) |
|
4147 return E_UNEXPECTED; |
|
4148 |
|
4149 HGLOBAL hMem = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT)); |
|
4150 if (!hMem) { |
|
4151 DeleteMetaFile(hMF); |
|
4152 return ResultFromScode(STG_E_MEDIUMFULL); |
|
4153 } |
|
4154 |
|
4155 LPMETAFILEPICT pMF = (LPMETAFILEPICT)GlobalLock(hMem); |
|
4156 pMF->hMF = hMF; |
|
4157 pMF->mm = MM_ANISOTROPIC; |
|
4158 pMF->xExt = MAP_PIX_TO_LOGHIM(width, qt.widget->logicalDpiX()); |
|
4159 pMF->yExt = MAP_PIX_TO_LOGHIM(height, qt.widget->logicalDpiY()); |
|
4160 GlobalUnlock(hMem); |
|
4161 |
|
4162 memset(pmedium, 0, sizeof(STGMEDIUM)); |
|
4163 pmedium->tymed = TYMED_MFPICT; |
|
4164 pmedium->hGlobal = hMem; |
|
4165 pmedium->pUnkForRelease = 0; |
|
4166 |
|
4167 return S_OK; |
|
4168 } |
|
4169 |
|
4170 /* |
|
4171 Not implemented. |
|
4172 */ |
|
4173 HRESULT WINAPI QAxServerBase::DAdvise(FORMATETC *pformatetc, DWORD advf, |
|
4174 IAdviseSink *pAdvSink, DWORD *pdwConnection) |
|
4175 { |
|
4176 if (pformatetc->dwAspect != DVASPECT_CONTENT) |
|
4177 return E_FAIL; |
|
4178 |
|
4179 *pdwConnection = adviseSinks.count() + 1; |
|
4180 STATDATA data = { |
|
4181 {pformatetc->cfFormat,pformatetc->ptd,pformatetc->dwAspect,pformatetc->lindex,pformatetc->tymed}, |
|
4182 advf, pAdvSink, *pdwConnection |
|
4183 }; |
|
4184 adviseSinks.append(data); |
|
4185 pAdvSink->AddRef(); |
|
4186 return S_OK; |
|
4187 } |
|
4188 |
|
4189 /* |
|
4190 Not implemented. |
|
4191 */ |
|
4192 HRESULT WINAPI QAxServerBase::DUnadvise(DWORD dwConnection) |
|
4193 { |
|
4194 return Unadvise(dwConnection); |
|
4195 } |
|
4196 |
|
4197 /* |
|
4198 Not implemented. |
|
4199 */ |
|
4200 HRESULT WINAPI QAxServerBase::EnumDAdvise(IEnumSTATDATA ** /*ppenumAdvise*/) |
|
4201 { |
|
4202 return E_NOTIMPL; |
|
4203 } |
|
4204 |
|
4205 /* |
|
4206 Not implemented. |
|
4207 */ |
|
4208 HRESULT WINAPI QAxServerBase::GetDataHere(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */) |
|
4209 { |
|
4210 return E_NOTIMPL; |
|
4211 } |
|
4212 |
|
4213 /* |
|
4214 Not implemented. |
|
4215 */ |
|
4216 HRESULT WINAPI QAxServerBase::QueryGetData(FORMATETC* /* pformatetc */) |
|
4217 { |
|
4218 return E_NOTIMPL; |
|
4219 } |
|
4220 |
|
4221 /* |
|
4222 Not implemented. |
|
4223 */ |
|
4224 HRESULT WINAPI QAxServerBase::GetCanonicalFormatEtc(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */) |
|
4225 { |
|
4226 return E_NOTIMPL; |
|
4227 } |
|
4228 |
|
4229 /* |
|
4230 Not implemented. |
|
4231 */ |
|
4232 HRESULT WINAPI QAxServerBase::SetData(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */) |
|
4233 { |
|
4234 return E_NOTIMPL; |
|
4235 } |
|
4236 |
|
4237 /* |
|
4238 Not implemented. |
|
4239 */ |
|
4240 HRESULT WINAPI QAxServerBase::EnumFormatEtc(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */) |
|
4241 { |
|
4242 return E_NOTIMPL; |
|
4243 } |
|
4244 |
|
4245 |
|
4246 |
|
4247 static int mapModifiers(int state) |
|
4248 { |
|
4249 int ole = 0; |
|
4250 if (state & Qt::ShiftModifier) |
|
4251 ole |= 1; |
|
4252 if (state & Qt::ControlModifier) |
|
4253 ole |= 2; |
|
4254 if (state & Qt::AltModifier) |
|
4255 ole |= 4; |
|
4256 |
|
4257 return ole; |
|
4258 } |
|
4259 |
|
4260 /* |
|
4261 \reimp |
|
4262 */ |
|
4263 bool QAxServerBase::eventFilter(QObject *o, QEvent *e) |
|
4264 { |
|
4265 if (!theObject) |
|
4266 return QObject::eventFilter(o, e); |
|
4267 |
|
4268 if ((e->type() == QEvent::Show || e->type() == QEvent::Hide) && (o == statusBar || o == menuBar)) { |
|
4269 if (o == menuBar) { |
|
4270 if (e->type() == QEvent::Hide) { |
|
4271 createMenu(menuBar); |
|
4272 } else if (e->type() == QEvent::Show) { |
|
4273 removeMenu(); |
|
4274 } |
|
4275 } else if (statusBar) { |
|
4276 statusBar->setSizeGripEnabled(false); |
|
4277 } |
|
4278 updateGeometry(); |
|
4279 if (m_spInPlaceSite && qt.widget->sizeHint().isValid()) { |
|
4280 RECT rect = {0, 0, qt.widget->sizeHint().width(), qt.widget->sizeHint().height()}; |
|
4281 m_spInPlaceSite->OnPosRectChange(&rect); |
|
4282 } |
|
4283 } |
|
4284 switch (e->type()) { |
|
4285 case QEvent::ChildAdded: |
|
4286 static_cast<QChildEvent*>(e)->child()->installEventFilter(this); |
|
4287 break; |
|
4288 case QEvent::ChildRemoved: |
|
4289 static_cast<QChildEvent*>(e)->child()->removeEventFilter(this); |
|
4290 break; |
|
4291 case QEvent::KeyPress: |
|
4292 if (o == qt.object && hasStockEvents) { |
|
4293 QKeyEvent *ke = (QKeyEvent*)e; |
|
4294 int key = ke->key(); |
|
4295 int state = ke->modifiers(); |
|
4296 void *argv[] = { |
|
4297 0, |
|
4298 &key, |
|
4299 &state |
|
4300 }; |
|
4301 qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_KEYDOWN, argv); |
|
4302 if (!ke->text().isEmpty()) |
|
4303 qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_KEYPRESS, argv); |
|
4304 } |
|
4305 break; |
|
4306 case QEvent::KeyRelease: |
|
4307 if (o == qt.object && hasStockEvents) { |
|
4308 QKeyEvent *ke = (QKeyEvent*)e; |
|
4309 int key = ke->key(); |
|
4310 int state = ke->modifiers(); |
|
4311 void *argv[] = { |
|
4312 0, |
|
4313 &key, |
|
4314 &state |
|
4315 }; |
|
4316 qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_KEYUP, argv); |
|
4317 } |
|
4318 break; |
|
4319 case QEvent::MouseMove: |
|
4320 if (o == qt.object && hasStockEvents) { |
|
4321 QMouseEvent *me = (QMouseEvent*)e; |
|
4322 int button = me->buttons() & Qt::MouseButtonMask; |
|
4323 int state = mapModifiers(me->modifiers()); |
|
4324 int x = me->x(); |
|
4325 int y = me->y(); |
|
4326 void *argv[] = { |
|
4327 0, |
|
4328 &button, |
|
4329 &state, |
|
4330 &x, |
|
4331 &y |
|
4332 }; |
|
4333 qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_MOUSEMOVE, argv); |
|
4334 } |
|
4335 break; |
|
4336 case QEvent::MouseButtonRelease: |
|
4337 if (o == qt.object && hasStockEvents) { |
|
4338 QMouseEvent *me = (QMouseEvent*)e; |
|
4339 int button = me->button(); |
|
4340 int state = mapModifiers(me->modifiers()); |
|
4341 int x = me->x(); |
|
4342 int y = me->y(); |
|
4343 void *argv[] = { |
|
4344 0, |
|
4345 &button, |
|
4346 &state, |
|
4347 &x, |
|
4348 &y |
|
4349 }; |
|
4350 qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_MOUSEUP, argv); |
|
4351 qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_CLICK, 0); |
|
4352 } |
|
4353 break; |
|
4354 case QEvent::MouseButtonDblClick: |
|
4355 if (o == qt.object && hasStockEvents) { |
|
4356 qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_DBLCLICK, 0); |
|
4357 } |
|
4358 break; |
|
4359 case QEvent::MouseButtonPress: |
|
4360 if (m_spInPlaceSite && !isUIActive) { |
|
4361 internalActivate(); |
|
4362 } |
|
4363 if (o == qt.widget && hasStockEvents) { |
|
4364 QMouseEvent *me = (QMouseEvent*)e; |
|
4365 int button = me->button(); |
|
4366 int state = mapModifiers(me->modifiers()); |
|
4367 int x = me->x(); |
|
4368 int y = me->y(); |
|
4369 void *argv[] = { |
|
4370 0, |
|
4371 &button, |
|
4372 &state, |
|
4373 &x, |
|
4374 &y |
|
4375 }; |
|
4376 qt_metacall(QMetaObject::InvokeMetaMethod, DISPID_MOUSEDOWN, argv); |
|
4377 } |
|
4378 break; |
|
4379 case QEvent::Show: |
|
4380 if (m_hWnd && o == qt.widget) |
|
4381 ShowWindow(m_hWnd, SW_SHOW); |
|
4382 updateMask(); |
|
4383 break; |
|
4384 case QEvent::Hide: |
|
4385 if (m_hWnd && o == qt.widget) |
|
4386 ShowWindow(m_hWnd, SW_HIDE); |
|
4387 break; |
|
4388 |
|
4389 case QEvent::EnabledChange: |
|
4390 if (m_hWnd && o == qt.widget) |
|
4391 EnableWindow(m_hWnd, qt.widget->isEnabled()); |
|
4392 // Fall Through |
|
4393 case QEvent::FontChange: |
|
4394 case QEvent::ActivationChange: |
|
4395 case QEvent::StyleChange: |
|
4396 case QEvent::IconTextChange: |
|
4397 case QEvent::ModifiedChange: |
|
4398 case QEvent::Resize: |
|
4399 updateMask(); |
|
4400 break; |
|
4401 case QEvent::WindowBlocked: { |
|
4402 if (!m_spInPlaceFrame) |
|
4403 break; |
|
4404 m_spInPlaceFrame->EnableModeless(FALSE); |
|
4405 MSG msg; |
|
4406 // Visual Basic 6.0 posts the message WM_USER+3078 from the EnableModeless(). |
|
4407 // While handling this message, VB will disable all current top-levels. After |
|
4408 // this we have to re-enable the Qt modal widget to receive input events. |
|
4409 if (PeekMessage(&msg, 0, WM_USER+3078, WM_USER+3078, PM_REMOVE)) { |
|
4410 TranslateMessage(&msg); |
|
4411 DispatchMessage(&msg); |
|
4412 QWidget *modalWidget = QApplication::activeModalWidget(); |
|
4413 if (modalWidget && modalWidget->isVisible() && modalWidget->isEnabled() |
|
4414 && !IsWindowEnabled(modalWidget->effectiveWinId())) |
|
4415 EnableWindow(modalWidget->effectiveWinId(), TRUE); |
|
4416 } |
|
4417 break; |
|
4418 } |
|
4419 case QEvent::WindowUnblocked: |
|
4420 if (!m_spInPlaceFrame) |
|
4421 break; |
|
4422 m_spInPlaceFrame->EnableModeless(TRUE); |
|
4423 break; |
|
4424 default: |
|
4425 break; |
|
4426 } |
|
4427 return QObject::eventFilter(o, e); |
|
4428 } |
|
4429 |
|
4430 QT_END_NAMESPACE |
|
4431 #endif // QT_NO_WIN_ACTIVEQT |