author | Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> |
Wed, 18 Aug 2010 10:37:55 +0300 | |
changeset 33 | 3e2da88830cd |
parent 30 | 5dc02b23752f |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
18
2f34d5167611
Revision: 201011
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 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 |
||
30
5dc02b23752f
Revision: 201025
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
18
diff
changeset
|
163 |
static LRESULT QT_WIN_CALLBACK ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); |
0 | 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 |
|
30
5dc02b23752f
Revision: 201025
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
18
diff
changeset
|
767 |
LRESULT QT_WIN_CALLBACK axs_FilterProc(int nCode, WPARAM wParam, LPARAM lParam) |
0 | 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 |
*/ |
|
30
5dc02b23752f
Revision: 201025
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
18
diff
changeset
|
1353 |
LRESULT QT_WIN_CALLBACK QAxServerBase::ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
0 | 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")); |
|
30
5dc02b23752f
Revision: 201025
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
18
diff
changeset
|
1539 |
cn += QString::number((quintptr)ActiveXProc); |
0 | 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>( |
|
30
5dc02b23752f
Revision: 201025
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
18
diff
changeset
|
1602 |
reinterpret_cast<quintptr>(createPopup(action->menu())) |
0 | 1603 |
); |
1604 |
} else { |
|
30
5dc02b23752f
Revision: 201025
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
18
diff
changeset
|
1605 |
itemId = static_cast<ushort>(reinterpret_cast<quintptr>(action)); |
0 | 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>( |
|
30
5dc02b23752f
Revision: 201025
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
18
diff
changeset
|
1649 |
reinterpret_cast<quintptr>(createPopup(action->menu())) |
0 | 1650 |
); |
1651 |
} else { |
|
30
5dc02b23752f
Revision: 201025
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
18
diff
changeset
|
1652 |
itemId = static_cast<ushort>(reinterpret_cast<quintptr>(action)); |
0 | 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 |