author | eckhart.koppen@nokia.com |
Wed, 31 Mar 2010 11:06:36 +0300 | |
changeset 7 | f7bc934e204c |
parent 0 | 1918ee327afb |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
7
f7bc934e204c
5cabc75a39ca2f064f70b40f72ed93c74c4dc19b
eckhart.koppen@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 |
#include "qaxwidget.h" |
|
42 |
||
43 |
#ifndef QT_NO_WIN_ACTIVEQT |
|
44 |
||
45 |
#include <ActiveQt/qaxaggregated.h> |
|
46 |
||
47 |
#include <qabstracteventdispatcher.h> |
|
48 |
#include <qapplication.h> |
|
49 |
#include <private/qapplication_p.h> |
|
50 |
#include <qdockwidget.h> |
|
51 |
#include <qevent.h> |
|
52 |
#include <qlayout.h> |
|
53 |
#include <qmainwindow.h> |
|
54 |
#include <qmenu.h> |
|
55 |
#include <qmenubar.h> |
|
56 |
#include <qmetaobject.h> |
|
57 |
#include <qpainter.h> |
|
58 |
#include <qpointer.h> |
|
59 |
#include <qregexp.h> |
|
60 |
#include <quuid.h> |
|
61 |
#include <qwhatsthis.h> |
|
62 |
||
63 |
#include <windowsx.h> |
|
64 |
#include <ocidl.h> |
|
65 |
#include <olectl.h> |
|
66 |
#include <docobj.h> |
|
67 |
||
68 |
// #define QAX_DEBUG |
|
69 |
||
70 |
#ifdef QAX_DEBUG |
|
71 |
#define AX_DEBUG(x) qDebug(#x); |
|
72 |
#else |
|
73 |
#define AX_DEBUG(x); |
|
74 |
#endif |
|
75 |
||
76 |
// #define QAX_SUPPORT_WINDOWLESS |
|
77 |
// #define QAX_SUPPORT_BORDERSPACE |
|
78 |
||
79 |
// missing interface from win32api |
|
80 |
#if defined(Q_CC_GNU) |
|
81 |
# if !defined(IOleInPlaceObjectWindowless) |
|
82 |
# undef INTERFACE |
|
83 |
# define INTERFACE IOleInPlaceObjectWindowless |
|
84 |
DECLARE_INTERFACE_(IOleInPlaceObjectWindowless,IOleInPlaceObject) |
|
85 |
{ |
|
86 |
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; |
|
87 |
STDMETHOD_(ULONG,AddRef)(THIS) PURE; |
|
88 |
STDMETHOD_(ULONG,Release)(THIS) PURE; |
|
89 |
STDMETHOD(GetWindow)(THIS_ HWND*) PURE; |
|
90 |
STDMETHOD(ContextSensitiveHelp)(THIS_ BOOL) PURE; |
|
91 |
STDMETHOD(InPlaceDeactivate)(THIS) PURE; |
|
92 |
STDMETHOD(UIDeactivate)(THIS) PURE; |
|
93 |
STDMETHOD(SetObjectRects)(THIS_ LPCRECT,LPCRECT) PURE; |
|
94 |
STDMETHOD(ReactivateAndUndo)(THIS) PURE; |
|
95 |
STDMETHOD(OnWindowMessage)(THIS_ UINT, WPARAM, LPARAM, LRESULT*) PURE; |
|
96 |
STDMETHOD(GetDropTarget)(THIS_ IDropTarget**) PURE; |
|
97 |
}; |
|
98 |
# endif |
|
99 |
#endif |
|
100 |
||
101 |
#include "../shared/qaxtypes.h" |
|
102 |
||
103 |
QT_BEGIN_NAMESPACE |
|
104 |
||
105 |
/* \class QAxHostWidget |
|
106 |
\brief The QAxHostWidget class is the actual container widget. |
|
107 |
||
108 |
\internal |
|
109 |
*/ |
|
110 |
class QAxHostWidget : public QWidget |
|
111 |
{ |
|
112 |
friend class QAxClientSite; |
|
113 |
public: |
|
114 |
Q_OBJECT_CHECK |
|
115 |
QAxHostWidget(QWidget *parent, QAxClientSite *ax); |
|
116 |
~QAxHostWidget(); |
|
117 |
||
118 |
QSize sizeHint() const; |
|
119 |
QSize minimumSizeHint() const; |
|
120 |
||
121 |
int qt_metacall(QMetaObject::Call, int isignal, void **argv); |
|
122 |
void* qt_metacast(const char *clname); |
|
123 |
||
124 |
inline QAxClientSite *clientSite() const |
|
125 |
{ |
|
126 |
return axhost; |
|
127 |
} |
|
128 |
||
129 |
protected: |
|
130 |
bool winEvent(MSG *msg, long *result); |
|
131 |
bool event(QEvent *e); |
|
132 |
bool eventFilter(QObject *o, QEvent *e); |
|
133 |
void resizeEvent(QResizeEvent *e); |
|
134 |
void focusInEvent(QFocusEvent *e); |
|
135 |
void focusOutEvent(QFocusEvent *e); |
|
136 |
void paintEvent(QPaintEvent *e); |
|
137 |
void showEvent(QShowEvent *e); |
|
138 |
QPaintEngine* paintEngine() const |
|
139 |
{ |
|
140 |
return 0; |
|
141 |
} |
|
142 |
||
143 |
private: |
|
144 |
void resizeObject(); |
|
145 |
||
146 |
int setFocusTimer; |
|
147 |
bool hasFocus; |
|
148 |
QAxClientSite *axhost; |
|
149 |
}; |
|
150 |
||
151 |
/* \class QAxClientSite |
|
152 |
\brief The QAxClientSite class implements the client site interfaces. |
|
153 |
||
154 |
\internal |
|
155 |
*/ |
|
156 |
class QAxClientSite : public IDispatch, |
|
157 |
public IOleClientSite, |
|
158 |
public IOleControlSite, |
|
159 |
#ifdef QAX_SUPPORT_WINDOWLESS |
|
160 |
public IOleInPlaceSiteWindowless, |
|
161 |
#else |
|
162 |
public IOleInPlaceSite, |
|
163 |
#endif |
|
164 |
public IOleInPlaceFrame, |
|
165 |
public IOleDocumentSite, |
|
166 |
public IAdviseSink |
|
167 |
{ |
|
168 |
friend class QAxHostWidget; |
|
169 |
public: |
|
170 |
QAxClientSite(QAxWidget *c); |
|
171 |
virtual ~QAxClientSite(); |
|
172 |
||
173 |
bool activateObject(bool initialized, const QByteArray &data); |
|
174 |
||
175 |
void releaseAll(); |
|
176 |
void deactivate(); |
|
177 |
inline void reset(QWidget *p) |
|
178 |
{ |
|
179 |
if (widget == p) |
|
180 |
widget = 0; |
|
181 |
else if (host == p) |
|
182 |
host = 0; |
|
183 |
} |
|
184 |
||
185 |
inline IOleInPlaceActiveObject *inPlaceObject() const |
|
186 |
{ |
|
187 |
return m_spInPlaceActiveObject; |
|
188 |
} |
|
189 |
||
190 |
inline HRESULT doVerb(LONG index) |
|
191 |
{ |
|
192 |
if (!m_spOleObject) |
|
193 |
return E_NOTIMPL; |
|
194 |
if (!host) |
|
195 |
return OLE_E_NOT_INPLACEACTIVE; |
|
196 |
||
197 |
RECT rcPos = { host->x(), host->y(), host->x()+host->width(), host->y()+host->height() }; |
|
198 |
return m_spOleObject->DoVerb(index, 0, this, 0, host->winId(), &rcPos); |
|
199 |
} |
|
200 |
||
201 |
// IUnknown |
|
202 |
unsigned long WINAPI AddRef(); |
|
203 |
unsigned long WINAPI Release(); |
|
204 |
STDMETHOD(QueryInterface)(REFIID iid, void **iface); |
|
205 |
||
206 |
// IDispatch |
|
207 |
HRESULT __stdcall GetTypeInfoCount(unsigned int *) { return E_NOTIMPL; } |
|
208 |
HRESULT __stdcall GetTypeInfo(UINT, LCID, ITypeInfo **) { return E_NOTIMPL; } |
|
209 |
HRESULT __stdcall GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *) { return E_NOTIMPL; } |
|
210 |
HRESULT __stdcall Invoke(DISPID dispIdMember, |
|
211 |
REFIID riid, |
|
212 |
LCID lcid, |
|
213 |
WORD wFlags, |
|
214 |
DISPPARAMS *pDispParams, |
|
215 |
VARIANT *pVarResult, |
|
216 |
EXCEPINFO *pExcepInfo, |
|
217 |
UINT *puArgErr); |
|
218 |
void emitAmbientPropertyChange(DISPID dispid); |
|
219 |
||
220 |
// IOleClientSite |
|
221 |
STDMETHOD(SaveObject)(); |
|
222 |
STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk); |
|
223 |
STDMETHOD(GetContainer)(LPOLECONTAINER FAR* ppContainer); |
|
224 |
STDMETHOD(ShowObject)(); |
|
225 |
STDMETHOD(OnShowWindow)(BOOL fShow); |
|
226 |
STDMETHOD(RequestNewObjectLayout)(); |
|
227 |
||
228 |
// IOleControlSite |
|
229 |
STDMETHOD(OnControlInfoChanged)(); |
|
230 |
STDMETHOD(LockInPlaceActive)(BOOL fLock); |
|
231 |
STDMETHOD(GetExtendedControl)(IDispatch** ppDisp); |
|
232 |
STDMETHOD(TransformCoords)(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags); |
|
233 |
STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, DWORD grfModifiers); |
|
234 |
STDMETHOD(OnFocus)(BOOL fGotFocus); |
|
235 |
STDMETHOD(ShowPropertyFrame)(); |
|
236 |
||
237 |
// IOleWindow |
|
238 |
STDMETHOD(GetWindow)(HWND *phwnd); |
|
239 |
STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode); |
|
240 |
||
241 |
// IOleInPlaceSite |
|
242 |
STDMETHOD(CanInPlaceActivate)(); |
|
243 |
STDMETHOD(OnInPlaceActivate)(); |
|
244 |
STDMETHOD(OnUIActivate)(); |
|
245 |
STDMETHOD(GetWindowContext)(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo); |
|
246 |
STDMETHOD(Scroll)(SIZE scrollExtant); |
|
247 |
STDMETHOD(OnUIDeactivate)(BOOL fUndoable); |
|
248 |
STDMETHOD(OnInPlaceDeactivate)(); |
|
249 |
STDMETHOD(DiscardUndoState)(); |
|
250 |
STDMETHOD(DeactivateAndUndo)(); |
|
251 |
STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect); |
|
252 |
||
253 |
#ifdef QAX_SUPPORT_WINDOWLESS |
|
254 |
// IOleInPlaceSiteEx ### |
|
255 |
STDMETHOD(OnInPlaceActivateEx)(BOOL* /*pfNoRedraw*/, DWORD /*dwFlags*/) |
|
256 |
{ |
|
257 |
return S_OK; |
|
258 |
} |
|
259 |
STDMETHOD(OnInPlaceDeactivateEx)(BOOL /*fNoRedraw*/) |
|
260 |
{ |
|
261 |
return S_OK; |
|
262 |
} |
|
263 |
STDMETHOD(RequestUIActivate)() |
|
264 |
{ |
|
265 |
return S_OK; |
|
266 |
} |
|
267 |
||
268 |
// IOleInPlaceSiteWindowless ### |
|
269 |
STDMETHOD(CanWindowlessActivate)() |
|
270 |
{ |
|
271 |
return S_OK; |
|
272 |
} |
|
273 |
STDMETHOD(GetCapture)() |
|
274 |
{ |
|
275 |
return S_FALSE; |
|
276 |
} |
|
277 |
STDMETHOD(SetCapture)(BOOL /*fCapture*/) |
|
278 |
{ |
|
279 |
return S_FALSE; |
|
280 |
} |
|
281 |
STDMETHOD(GetFocus)() |
|
282 |
{ |
|
283 |
return S_FALSE; |
|
284 |
} |
|
285 |
STDMETHOD(SetFocus)(BOOL /*fCapture*/) |
|
286 |
{ |
|
287 |
return S_FALSE; |
|
288 |
} |
|
289 |
STDMETHOD(GetDC)(LPCRECT /*pRect*/, DWORD /*grfFlags*/, HDC *phDC) |
|
290 |
{ |
|
291 |
*phDC = 0; |
|
292 |
return S_OK; |
|
293 |
} |
|
294 |
STDMETHOD(ReleaseDC)(HDC hDC) |
|
295 |
{ |
|
296 |
::ReleaseDC(widget->winId(), hDC); |
|
297 |
return S_OK; |
|
298 |
} |
|
299 |
STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase) |
|
300 |
{ |
|
301 |
::InvalidateRect(host->winId(), pRect, fErase); |
|
302 |
return S_OK; |
|
303 |
} |
|
304 |
STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase) |
|
305 |
{ |
|
306 |
::InvalidateRgn(host->winId(), hRGN, fErase); |
|
307 |
return S_OK; |
|
308 |
} |
|
309 |
STDMETHOD(ScrollRect)(int /*dx*/, int /*dy*/, LPCRECT /*pRectScroll*/, LPCRECT /*pRectClip*/) |
|
310 |
{ |
|
311 |
return S_OK; |
|
312 |
} |
|
313 |
STDMETHOD(AdjustRect)(LPRECT /*prc*/) |
|
314 |
{ |
|
315 |
return S_OK; |
|
316 |
} |
|
317 |
#ifdef Q_CC_GNU // signature incorrect in win32api |
|
318 |
STDMETHOD(AdjustRect)(LPCRECT /*prc*/) |
|
319 |
{ |
|
320 |
RECT rect; |
|
321 |
return AdjustRect(&rect); |
|
322 |
} |
|
323 |
#endif |
|
324 |
||
325 |
STDMETHOD(OnDefWindowMessage)(UINT /*msg*/, WPARAM /*wPara*/, LPARAM /*lParam*/, LRESULT* /*plResult*/) |
|
326 |
{ |
|
327 |
return S_FALSE; |
|
328 |
} |
|
329 |
#endif |
|
330 |
||
331 |
// IOleInPlaceFrame |
|
332 |
STDMETHOD(InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)); |
|
333 |
STDMETHOD(SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)); |
|
334 |
STDMETHOD(RemoveMenus(HMENU hmenuShared)); |
|
335 |
STDMETHOD(SetStatusText(LPCOLESTR pszStatusText)); |
|
336 |
STDMETHOD(EnableModeless(BOOL fEnable)); |
|
337 |
STDMETHOD(TranslateAccelerator(LPMSG lpMsg, WORD grfModifiers)); |
|
338 |
||
339 |
// IOleInPlaceUIWindow |
|
340 |
STDMETHOD(GetBorder(LPRECT lprectBorder)); |
|
341 |
STDMETHOD(RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)); |
|
342 |
STDMETHOD(SetBorderSpace(LPCBORDERWIDTHS pborderwidths)); |
|
343 |
STDMETHOD(SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)); |
|
344 |
||
345 |
// IOleDocumentSite |
|
346 |
STDMETHOD(ActivateMe(IOleDocumentView *pViewToActivate)); |
|
347 |
||
348 |
// IAdviseSink |
|
349 |
STDMETHOD_(void, OnDataChange)(FORMATETC* /*pFormatetc*/, STGMEDIUM* /*pStgmed*/) |
|
350 |
{ |
|
351 |
AX_DEBUG(QAxClientSite::OnDataChange); |
|
352 |
} |
|
353 |
STDMETHOD_(void, OnViewChange)(DWORD /*dwAspect*/, LONG /*lindex*/) |
|
354 |
{ |
|
355 |
AX_DEBUG(QAxClientSite::OnViewChange); |
|
356 |
} |
|
357 |
STDMETHOD_(void, OnRename)(IMoniker* /*pmk*/) |
|
358 |
{ |
|
359 |
} |
|
360 |
STDMETHOD_(void, OnSave)() |
|
361 |
{ |
|
362 |
} |
|
363 |
STDMETHOD_(void, OnClose)() |
|
364 |
{ |
|
365 |
} |
|
366 |
||
367 |
QSize sizeHint() const { return sizehint; } |
|
368 |
QSize minimumSizeHint() const; |
|
369 |
inline void resize(QSize sz) { if (host) host->resize(sz); } |
|
370 |
||
371 |
bool translateKeyEvent(int message, int keycode) const |
|
372 |
{ |
|
373 |
if (!widget) |
|
374 |
return false; |
|
375 |
return widget->translateKeyEvent(message, keycode); |
|
376 |
} |
|
377 |
||
378 |
int qt_metacall(QMetaObject::Call, int isignal, void **argv); |
|
379 |
void windowActivationChange(); |
|
380 |
||
381 |
bool eventTranslated : 1; |
|
382 |
||
383 |
private: |
|
384 |
#if !defined(Q_WS_WINCE) |
|
385 |
struct OleMenuItem { |
|
386 |
OleMenuItem(HMENU hm = 0, int ID = 0, QMenu *menu = 0) |
|
387 |
: hMenu(hm), id(ID), subMenu(menu) |
|
388 |
{} |
|
389 |
HMENU hMenu; |
|
390 |
int id; |
|
391 |
QMenu *subMenu; |
|
392 |
}; |
|
393 |
QMenu *generatePopup(HMENU subMenu, QWidget *parent); |
|
394 |
#endif |
|
395 |
||
396 |
IOleObject *m_spOleObject; |
|
397 |
IOleControl *m_spOleControl; |
|
398 |
IOleInPlaceObjectWindowless *m_spInPlaceObject; |
|
399 |
IOleInPlaceActiveObject *m_spInPlaceActiveObject; |
|
400 |
IOleDocumentView *m_spActiveView; |
|
401 |
||
402 |
QAxAggregated *aggregatedObject; |
|
403 |
||
404 |
bool inPlaceObjectWindowless :1; |
|
405 |
bool inPlaceModelessEnabled :1; |
|
406 |
bool canHostDocument : 1; |
|
407 |
||
408 |
DWORD m_dwOleObject; |
|
409 |
#if !defined(Q_WS_WINCE) |
|
410 |
HWND m_menuOwner; |
|
411 |
#endif |
|
412 |
CONTROLINFO control_info; |
|
413 |
||
414 |
QSize sizehint; |
|
415 |
unsigned long ref; |
|
416 |
QAxWidget *widget; |
|
417 |
QAxHostWidget *host; |
|
418 |
#if !defined(Q_WS_WINCE) |
|
419 |
QPointer<QMenuBar> menuBar; |
|
420 |
QMap<QAction*,OleMenuItem> menuItemMap; |
|
421 |
#endif |
|
422 |
}; |
|
423 |
||
424 |
static const ushort mouseTbl[] = { |
|
425 |
WM_MOUSEMOVE, QEvent::MouseMove, 0, |
|
426 |
WM_LBUTTONDOWN, QEvent::MouseButtonPress, Qt::LeftButton, |
|
427 |
WM_LBUTTONUP, QEvent::MouseButtonRelease, Qt::LeftButton, |
|
428 |
WM_LBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::LeftButton, |
|
429 |
WM_RBUTTONDOWN, QEvent::MouseButtonPress, Qt::RightButton, |
|
430 |
WM_RBUTTONUP, QEvent::MouseButtonRelease, Qt::RightButton, |
|
431 |
WM_RBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::RightButton, |
|
432 |
WM_MBUTTONDOWN, QEvent::MouseButtonPress, Qt::MidButton, |
|
433 |
WM_MBUTTONUP, QEvent::MouseButtonRelease, Qt::MidButton, |
|
434 |
WM_MBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::MidButton, |
|
435 |
0, 0, 0 |
|
436 |
}; |
|
437 |
||
438 |
static Qt::MouseButtons translateMouseButtonState(int s) |
|
439 |
{ |
|
440 |
Qt::MouseButtons bst = 0; |
|
441 |
if (s & MK_LBUTTON) |
|
442 |
bst |= Qt::LeftButton; |
|
443 |
if (s & MK_MBUTTON) |
|
444 |
bst |= Qt::MidButton; |
|
445 |
if (s & MK_RBUTTON) |
|
446 |
bst |= Qt::RightButton; |
|
447 |
||
448 |
return bst; |
|
449 |
} |
|
450 |
||
451 |
static Qt::KeyboardModifiers translateModifierState(int s) |
|
452 |
{ |
|
453 |
Qt::KeyboardModifiers bst = 0; |
|
454 |
if (s & MK_SHIFT) |
|
455 |
bst |= Qt::ShiftModifier; |
|
456 |
if (s & MK_CONTROL) |
|
457 |
bst |= Qt::ControlModifier; |
|
458 |
if (GetKeyState(VK_MENU) < 0) |
|
459 |
bst |= Qt::AltModifier; |
|
460 |
||
461 |
return bst; |
|
462 |
} |
|
463 |
||
464 |
static QAbstractEventDispatcher::EventFilter previous_filter = 0; |
|
465 |
#if QT_VERSION >= 0x050000 |
|
466 |
#error "Fix QAbstractEventDispatcher::setEventFilter" |
|
467 |
#endif |
|
468 |
#if defined(Q_WS_WINCE) |
|
469 |
static int filter_ref = 0; |
|
470 |
#else |
|
471 |
static const wchar_t *qaxatom = L"QAxContainer4_Atom"; |
|
472 |
#endif |
|
473 |
||
474 |
// The filter procedure listening to user interaction on the control |
|
475 |
bool axc_FilterProc(void *m) |
|
476 |
{ |
|
477 |
MSG *msg = (MSG*)m; |
|
478 |
const uint message = msg->message; |
|
479 |
if ((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) || (message >= WM_KEYFIRST && message <= WM_KEYLAST)) { |
|
480 |
HWND hwnd = msg->hwnd; |
|
481 |
QAxWidget *ax = 0; |
|
482 |
QAxHostWidget *host = 0; |
|
483 |
while (!host && hwnd) { |
|
484 |
QWidget *widget = QWidget::find(hwnd); |
|
485 |
if (widget && widget->inherits("QAxHostWidget")) |
|
486 |
host = qobject_cast<QAxHostWidget*>(widget); |
|
487 |
hwnd = ::GetParent(hwnd); |
|
488 |
} |
|
489 |
if (host) |
|
490 |
ax = qobject_cast<QAxWidget*>(host->parentWidget()); |
|
491 |
if (ax && msg->hwnd != host->winId()) { |
|
492 |
if (message >= WM_KEYFIRST && message <= WM_KEYLAST) { |
|
493 |
QAxClientSite *site = host->clientSite(); |
|
494 |
site->eventTranslated = true; // reset in QAxClientSite::TranslateAccelerator |
|
495 |
HRESULT hres = S_FALSE; |
|
496 |
if (site && site->inPlaceObject() && site->translateKeyEvent(msg->message, msg->wParam)) |
|
497 |
hres = site->inPlaceObject()->TranslateAccelerator(msg); |
|
498 |
// if the object calls our TranslateAccelerator implementation, then continue with normal event processing |
|
499 |
// otherwise the object has translated the accelerator, and the event should be stopped |
|
500 |
if (site->eventTranslated && hres == S_OK) |
|
501 |
return true; |
|
502 |
} else { |
|
503 |
int i; |
|
504 |
for (i = 0; (UINT)mouseTbl[i] != message && mouseTbl[i]; i += 3) |
|
505 |
; |
|
506 |
||
507 |
if (mouseTbl[i]) { |
|
508 |
QEvent::Type type = (QEvent::Type)mouseTbl[++i]; |
|
509 |
int button = mouseTbl[++i]; |
|
510 |
if (type != QEvent::MouseMove || ax->hasMouseTracking() || button) { |
|
511 |
if (type == QEvent::MouseMove) |
|
512 |
button = 0; |
|
513 |
||
514 |
DWORD ol_pos = GetMessagePos(); |
|
515 |
QPoint gpos(GET_X_LPARAM(ol_pos), GET_Y_LPARAM(ol_pos)); |
|
516 |
QPoint pos = ax->mapFromGlobal(gpos); |
|
517 |
||
518 |
QMouseEvent e(type, pos, gpos, (Qt::MouseButton)button, |
|
519 |
translateMouseButtonState(msg->wParam), |
|
520 |
translateModifierState(msg->wParam)); |
|
521 |
QApplication::sendEvent(ax, &e); |
|
522 |
} |
|
523 |
} |
|
524 |
} |
|
525 |
} |
|
526 |
} |
|
527 |
||
528 |
if (previous_filter) |
|
529 |
return previous_filter(m); |
|
530 |
||
531 |
return false; |
|
532 |
} |
|
533 |
||
534 |
QAxClientSite::QAxClientSite(QAxWidget *c) |
|
535 |
: eventTranslated(true), ref(1), widget(c), host(0) |
|
536 |
{ |
|
537 |
aggregatedObject = widget->createAggregate(); |
|
538 |
if (aggregatedObject) { |
|
539 |
aggregatedObject->controlling_unknown = (IUnknown*)(IDispatch*)this; |
|
540 |
aggregatedObject->the_object = c; |
|
541 |
} |
|
542 |
||
543 |
m_spOleObject = 0; |
|
544 |
m_spOleControl = 0; |
|
545 |
m_spInPlaceObject = 0; |
|
546 |
m_spInPlaceActiveObject = 0; |
|
547 |
m_spActiveView = 0; |
|
548 |
||
549 |
inPlaceObjectWindowless = false; |
|
550 |
inPlaceModelessEnabled = true; |
|
551 |
canHostDocument = false; |
|
552 |
||
553 |
m_dwOleObject = 0; |
|
554 |
#if !defined(Q_WS_WINCE) |
|
555 |
m_menuOwner = 0; |
|
556 |
menuBar = 0; |
|
557 |
#endif |
|
558 |
memset(&control_info, 0, sizeof(control_info)); |
|
559 |
} |
|
560 |
||
561 |
bool QAxClientSite::activateObject(bool initialized, const QByteArray &data) |
|
562 |
{ |
|
563 |
if (!host) |
|
564 |
host = new QAxHostWidget(widget, this); |
|
565 |
||
566 |
bool showHost = false; |
|
567 |
HRESULT hr = S_OK; |
|
568 |
if (!m_spOleObject) |
|
569 |
widget->queryInterface(IID_IOleObject, (void**)&m_spOleObject); |
|
570 |
if (m_spOleObject) { |
|
571 |
DWORD dwMiscStatus = 0; |
|
572 |
m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus); |
|
573 |
||
574 |
#if !defined(Q_OS_WINCE) |
|
575 |
IOleDocument *document = 0; |
|
576 |
m_spOleObject->QueryInterface(IID_IOleDocument, (void**)&document); |
|
577 |
if (document) { |
|
578 |
IPersistStorage *persistStorage = 0; |
|
579 |
document->QueryInterface(IID_IPersistStorage, (void**)&persistStorage); |
|
580 |
if (persistStorage) { |
|
581 |
// try to activate as document server |
|
582 |
IStorage *storage = 0; |
|
583 |
ILockBytes * bytes = 0; |
|
584 |
HRESULT hres = ::CreateILockBytesOnHGlobal(0, TRUE, &bytes); |
|
585 |
hres = ::StgCreateDocfileOnILockBytes(bytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &storage); |
|
586 |
||
587 |
persistStorage->InitNew(storage); |
|
588 |
persistStorage->Release(); |
|
589 |
canHostDocument = true; |
|
590 |
storage->Release(); |
|
591 |
bytes->Release(); |
|
592 |
||
593 |
m_spOleObject->SetClientSite(this); |
|
594 |
OleRun(m_spOleObject); |
|
595 |
} |
|
596 |
document->Release(); |
|
597 |
} |
|
598 |
#endif |
|
599 |
||
600 |
if (!canHostDocument) { |
|
601 |
// activate as control |
|
602 |
if(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) |
|
603 |
m_spOleObject->SetClientSite(this); |
|
604 |
||
605 |
if (!initialized) { |
|
606 |
IPersistStreamInit *spPSI = 0; |
|
607 |
m_spOleObject->QueryInterface(IID_IPersistStreamInit, (void**)&spPSI); |
|
608 |
if (spPSI) { |
|
609 |
if (data.length()) { |
|
610 |
IStream *pStream = 0; |
|
611 |
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, data.length()); |
|
612 |
if (hGlobal) { |
|
613 |
BYTE *pStByte = (BYTE *)GlobalLock(hGlobal); |
|
614 |
if (pStByte) |
|
615 |
memcpy(pStByte, data.data(), data.length()); |
|
616 |
GlobalUnlock(hGlobal); |
|
617 |
if (SUCCEEDED(CreateStreamOnHGlobal(hGlobal, TRUE, &pStream))) { |
|
618 |
spPSI->Load(pStream); |
|
619 |
pStream->Release(); |
|
620 |
} |
|
621 |
GlobalFree(hGlobal); |
|
622 |
} |
|
623 |
} else { |
|
624 |
spPSI->InitNew(); |
|
625 |
} |
|
626 |
spPSI->Release(); |
|
627 |
} else if (data.length()) { //try initializing using a IPersistStorage |
|
628 |
IPersistStorage *spPS = 0; |
|
629 |
m_spOleObject->QueryInterface( IID_IPersistStorage, (void**)&spPS ); |
|
630 |
if (spPS) { |
|
631 |
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, data.length()); |
|
632 |
if (hGlobal) { |
|
633 |
#if !defined(Q_OS_WINCE) |
|
634 |
BYTE* pbData = (BYTE*)GlobalLock(hGlobal); |
|
635 |
if (pbData) |
|
636 |
memcpy(pbData, data.data(), data.length()); |
|
637 |
GlobalUnlock(hGlobal); |
|
638 |
// open an IStorage on the data and pass it to Load |
|
639 |
LPLOCKBYTES pLockBytes = 0; |
|
640 |
if (SUCCEEDED(CreateILockBytesOnHGlobal(hGlobal, TRUE, &pLockBytes))) { |
|
641 |
LPSTORAGE pStorage = 0; |
|
642 |
if (SUCCEEDED(StgOpenStorageOnILockBytes(pLockBytes, 0, |
|
643 |
STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStorage))) { |
|
644 |
spPS->Load(pStorage); |
|
645 |
pStorage->Release(); |
|
646 |
} |
|
647 |
pLockBytes->Release(); |
|
648 |
} |
|
649 |
GlobalFree(hGlobal); |
|
650 |
#endif |
|
651 |
} |
|
652 |
spPS->Release(); |
|
653 |
} |
|
654 |
} |
|
655 |
} |
|
656 |
||
657 |
if(!(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) |
|
658 |
m_spOleObject->SetClientSite(this); |
|
659 |
} |
|
660 |
||
661 |
IViewObject *spViewObject = 0; |
|
662 |
m_spOleObject->QueryInterface(IID_IViewObject, (void**) &spViewObject); |
|
663 |
||
664 |
m_spOleObject->Advise(this, &m_dwOleObject); |
|
665 |
IAdviseSink *spAdviseSink = 0; |
|
666 |
QueryInterface(IID_IAdviseSink, (void**)&spAdviseSink); |
|
667 |
if (spAdviseSink && spViewObject) { |
|
668 |
if (spViewObject) |
|
669 |
spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink); |
|
670 |
spAdviseSink->Release(); |
|
671 |
} |
|
672 |
if (spViewObject) |
|
673 |
spViewObject->Release(); |
|
674 |
||
675 |
m_spOleObject->SetHostNames(OLESTR("AXWIN"), 0); |
|
676 |
||
677 |
if (!(dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)) { |
|
678 |
SIZEL hmSize; |
|
679 |
hmSize.cx = MAP_PIX_TO_LOGHIM(250, widget->logicalDpiX()); |
|
680 |
hmSize.cy = MAP_PIX_TO_LOGHIM(250, widget->logicalDpiY()); |
|
681 |
||
682 |
m_spOleObject->SetExtent(DVASPECT_CONTENT, &hmSize); |
|
683 |
m_spOleObject->GetExtent(DVASPECT_CONTENT, &hmSize); |
|
684 |
||
685 |
sizehint.setWidth(MAP_LOGHIM_TO_PIX(hmSize.cx, widget->logicalDpiX())); |
|
686 |
sizehint.setHeight(MAP_LOGHIM_TO_PIX(hmSize.cy, widget->logicalDpiY())); |
|
687 |
showHost = true; |
|
688 |
} else { |
|
689 |
sizehint = QSize(0, 0); |
|
690 |
host->hide(); |
|
691 |
} |
|
692 |
if (!(dwMiscStatus & OLEMISC_NOUIACTIVATE)) { |
|
693 |
host->setFocusPolicy(Qt::StrongFocus); |
|
694 |
} else { |
|
695 |
host->setFocusPolicy(Qt::NoFocus); |
|
696 |
} |
|
697 |
||
698 |
RECT rcPos = { host->x(), host->y(), host->x()+sizehint.width(), host->y()+sizehint.height() }; |
|
699 |
||
700 |
hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, 0, (IOleClientSite*)this, 0, host->winId(), &rcPos); |
|
701 |
||
702 |
if (!m_spOleControl) |
|
703 |
m_spOleObject->QueryInterface(IID_IOleControl, (void**)&m_spOleControl); |
|
704 |
if (m_spOleControl) { |
|
705 |
m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_BACKCOLOR); |
|
706 |
m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_FORECOLOR); |
|
707 |
m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_FONT); |
|
708 |
m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_USERMODE); |
|
709 |
||
710 |
control_info.cb = sizeof(control_info); |
|
711 |
m_spOleControl->GetControlInfo(&control_info); |
|
712 |
} |
|
713 |
||
714 |
BSTR userType; |
|
715 |
HRESULT result = m_spOleObject->GetUserType(USERCLASSTYPE_SHORT, &userType); |
|
716 |
if (result == S_OK) { |
|
717 |
widget->setWindowTitle(QString::fromWCharArray(userType)); |
|
718 |
CoTaskMemFree(userType); |
|
719 |
} |
|
720 |
} else { |
|
721 |
IObjectWithSite *spSite = 0; |
|
722 |
widget->queryInterface(IID_IObjectWithSite, (void**)&spSite); |
|
723 |
if (spSite) { |
|
724 |
spSite->SetSite((IUnknown*)(IDispatch*)this); |
|
725 |
spSite->Release(); |
|
726 |
} |
|
727 |
} |
|
728 |
||
729 |
host->resize(widget->size()); |
|
730 |
if (showHost) |
|
731 |
host->show(); |
|
732 |
||
733 |
if (host->focusPolicy() != Qt::NoFocus) { |
|
734 |
widget->setFocusProxy(host); |
|
735 |
widget->setFocusPolicy(host->focusPolicy()); |
|
736 |
} |
|
737 |
||
738 |
return true; |
|
739 |
} |
|
740 |
||
741 |
QAxClientSite::~QAxClientSite() |
|
742 |
{ |
|
743 |
if (host) { |
|
744 |
host->axhost = 0; |
|
745 |
} |
|
746 |
||
747 |
if (aggregatedObject) |
|
748 |
aggregatedObject->the_object = 0; |
|
749 |
delete aggregatedObject; |
|
750 |
delete host; |
|
751 |
} |
|
752 |
||
753 |
void QAxClientSite::releaseAll() |
|
754 |
{ |
|
755 |
if (m_spOleObject) { |
|
756 |
m_spOleObject->SetClientSite(0); |
|
757 |
m_spOleObject->Unadvise(m_dwOleObject); |
|
758 |
m_spOleObject->Release(); |
|
759 |
} |
|
760 |
m_spOleObject = 0; |
|
761 |
if (m_spOleControl) m_spOleControl->Release(); |
|
762 |
m_spOleControl = 0; |
|
763 |
if (m_spInPlaceObject) m_spInPlaceObject->Release(); |
|
764 |
m_spInPlaceObject = 0; |
|
765 |
if (m_spInPlaceActiveObject) m_spInPlaceActiveObject->Release(); |
|
766 |
m_spInPlaceActiveObject = 0; |
|
767 |
||
768 |
inPlaceObjectWindowless = false; |
|
769 |
} |
|
770 |
||
771 |
void QAxClientSite::deactivate() |
|
772 |
{ |
|
773 |
if (m_spInPlaceObject) m_spInPlaceObject->InPlaceDeactivate(); |
|
774 |
// if this assertion fails the control didn't call OnInPlaceDeactivate |
|
775 |
Q_ASSERT(m_spInPlaceObject == 0); |
|
776 |
} |
|
777 |
||
778 |
//**** IUnknown |
|
779 |
unsigned long WINAPI QAxClientSite::AddRef() |
|
780 |
{ |
|
781 |
return ++ref; |
|
782 |
} |
|
783 |
||
784 |
unsigned long WINAPI QAxClientSite::Release() |
|
785 |
{ |
|
786 |
if (!--ref) { |
|
787 |
delete this; |
|
788 |
return 0; |
|
789 |
} |
|
790 |
return ref; |
|
791 |
} |
|
792 |
||
793 |
HRESULT WINAPI QAxClientSite::QueryInterface(REFIID iid, void **iface) |
|
794 |
{ |
|
795 |
*iface = 0; |
|
796 |
||
797 |
if (iid == IID_IUnknown) { |
|
798 |
*iface = (IUnknown*)(IDispatch*)this; |
|
799 |
} else { |
|
800 |
HRESULT res = S_OK; |
|
801 |
if (aggregatedObject) |
|
802 |
res = aggregatedObject->queryInterface(iid, iface); |
|
803 |
if (*iface) |
|
804 |
return res; |
|
805 |
} |
|
806 |
||
807 |
if (!(*iface)) { |
|
808 |
if (iid == IID_IDispatch) |
|
809 |
*iface = (IDispatch*)this; |
|
810 |
else if (iid == IID_IOleClientSite) |
|
811 |
*iface = (IOleClientSite*)this; |
|
812 |
else if (iid == IID_IOleControlSite) |
|
813 |
*iface = (IOleControlSite*)this; |
|
814 |
else if (iid == IID_IOleWindow) |
|
815 |
*iface = (IOleWindow*)(IOleInPlaceSite*)this; |
|
816 |
else if (iid == IID_IOleInPlaceSite) |
|
817 |
*iface = (IOleInPlaceSite*)this; |
|
818 |
#ifdef QAX_SUPPORT_WINDOWLESS |
|
819 |
else if (iid == IID_IOleInPlaceSiteEx) |
|
820 |
*iface = (IOleInPlaceSiteEx*)this; |
|
821 |
else if (iid == IID_IOleInPlaceSiteWindowless) |
|
822 |
*iface = (IOleInPlaceSiteWindowless*)this; |
|
823 |
#endif |
|
824 |
else if (iid == IID_IOleInPlaceFrame) |
|
825 |
*iface = (IOleInPlaceFrame*)this; |
|
826 |
else if (iid == IID_IOleInPlaceUIWindow) |
|
827 |
*iface = (IOleInPlaceUIWindow*)this; |
|
828 |
else if (iid == IID_IOleDocumentSite && canHostDocument) |
|
829 |
*iface = (IOleDocumentSite*)this; |
|
830 |
else if (iid == IID_IAdviseSink) |
|
831 |
*iface = (IAdviseSink*)this; |
|
832 |
} |
|
833 |
if (!*iface) |
|
834 |
return E_NOINTERFACE; |
|
835 |
||
836 |
AddRef(); |
|
837 |
return S_OK; |
|
838 |
} |
|
839 |
||
840 |
bool qax_runsInDesignMode = false; |
|
841 |
||
842 |
//**** IDispatch |
|
843 |
HRESULT WINAPI QAxClientSite::Invoke(DISPID dispIdMember, |
|
844 |
REFIID /*riid*/, |
|
845 |
LCID /*lcid*/, |
|
846 |
WORD /*wFlags*/, |
|
847 |
DISPPARAMS * /*pDispParams*/, |
|
848 |
VARIANT *pVarResult, |
|
849 |
EXCEPINFO * /*pExcepInfo*/, |
|
850 |
UINT * /*puArgErr*/) |
|
851 |
{ |
|
852 |
if (!pVarResult) |
|
853 |
return E_POINTER; |
|
854 |
if (!widget || !host) |
|
855 |
return E_UNEXPECTED; |
|
856 |
||
857 |
switch(dispIdMember) { |
|
858 |
case DISPID_AMBIENT_USERMODE: |
|
859 |
pVarResult->vt = VT_BOOL; |
|
860 |
pVarResult->boolVal = !qax_runsInDesignMode; |
|
861 |
return S_OK; |
|
862 |
||
863 |
case DISPID_AMBIENT_AUTOCLIP: |
|
864 |
case DISPID_AMBIENT_SUPPORTSMNEMONICS: |
|
865 |
pVarResult->vt = VT_BOOL; |
|
866 |
pVarResult->boolVal = true; |
|
867 |
return S_OK; |
|
868 |
||
869 |
case DISPID_AMBIENT_SHOWHATCHING: |
|
870 |
case DISPID_AMBIENT_SHOWGRABHANDLES: |
|
871 |
case DISPID_AMBIENT_DISPLAYASDEFAULT: |
|
872 |
case DISPID_AMBIENT_MESSAGEREFLECT: |
|
873 |
pVarResult->vt = VT_BOOL; |
|
874 |
pVarResult->boolVal = false; |
|
875 |
return S_OK; |
|
876 |
||
877 |
case DISPID_AMBIENT_DISPLAYNAME: |
|
878 |
pVarResult->vt = VT_BSTR; |
|
879 |
pVarResult->bstrVal = QStringToBSTR(widget->windowTitle()); |
|
880 |
return S_OK; |
|
881 |
||
882 |
case DISPID_AMBIENT_FONT: |
|
883 |
QVariantToVARIANT(widget->font(), *pVarResult); |
|
884 |
return S_OK; |
|
885 |
||
886 |
case DISPID_AMBIENT_BACKCOLOR: |
|
887 |
pVarResult->vt = VT_UI4; |
|
888 |
pVarResult->lVal = QColorToOLEColor(widget->palette().color(widget->backgroundRole())); |
|
889 |
return S_OK; |
|
890 |
||
891 |
case DISPID_AMBIENT_FORECOLOR: |
|
892 |
pVarResult->vt = VT_UI4; |
|
893 |
pVarResult->lVal = QColorToOLEColor(widget->palette().color(widget->foregroundRole())); |
|
894 |
return S_OK; |
|
895 |
||
896 |
case DISPID_AMBIENT_UIDEAD: |
|
897 |
pVarResult->vt = VT_BOOL; |
|
898 |
pVarResult->boolVal = !widget->isEnabled(); |
|
899 |
return S_OK; |
|
900 |
||
901 |
default: |
|
902 |
break; |
|
903 |
} |
|
904 |
||
905 |
return DISP_E_MEMBERNOTFOUND; |
|
906 |
} |
|
907 |
||
908 |
void QAxClientSite::emitAmbientPropertyChange(DISPID dispid) |
|
909 |
{ |
|
910 |
if (m_spOleControl) |
|
911 |
m_spOleControl->OnAmbientPropertyChange(dispid); |
|
912 |
} |
|
913 |
||
914 |
//**** IOleClientSite |
|
915 |
HRESULT WINAPI QAxClientSite::SaveObject() |
|
916 |
{ |
|
917 |
return E_NOTIMPL; |
|
918 |
} |
|
919 |
||
920 |
HRESULT WINAPI QAxClientSite::GetMoniker(DWORD, DWORD, IMoniker **ppmk) |
|
921 |
{ |
|
922 |
if (!ppmk) |
|
923 |
return E_POINTER; |
|
924 |
||
925 |
*ppmk = 0; |
|
926 |
return E_NOTIMPL; |
|
927 |
} |
|
928 |
||
929 |
HRESULT WINAPI QAxClientSite::GetContainer(LPOLECONTAINER *ppContainer) |
|
930 |
{ |
|
931 |
if (!ppContainer) |
|
932 |
return E_POINTER; |
|
933 |
||
934 |
*ppContainer = 0; |
|
935 |
return E_NOINTERFACE; |
|
936 |
} |
|
937 |
||
938 |
HRESULT WINAPI QAxClientSite::ShowObject() |
|
939 |
{ |
|
940 |
return S_OK; |
|
941 |
} |
|
942 |
||
943 |
HRESULT WINAPI QAxClientSite::OnShowWindow(BOOL /*fShow*/) |
|
944 |
{ |
|
945 |
return S_OK; |
|
946 |
} |
|
947 |
||
948 |
HRESULT WINAPI QAxClientSite::RequestNewObjectLayout() |
|
949 |
{ |
|
950 |
return E_NOTIMPL; |
|
951 |
} |
|
952 |
||
953 |
//**** IOleControlSite |
|
954 |
HRESULT WINAPI QAxClientSite::OnControlInfoChanged() |
|
955 |
{ |
|
956 |
if (m_spOleControl) |
|
957 |
m_spOleControl->GetControlInfo(&control_info); |
|
958 |
||
959 |
return S_OK; |
|
960 |
} |
|
961 |
||
962 |
HRESULT WINAPI QAxClientSite::LockInPlaceActive(BOOL /*fLock*/) |
|
963 |
{ |
|
964 |
AX_DEBUG(QAxClientSite::LockInPlaceActive); |
|
965 |
return S_OK; |
|
966 |
} |
|
967 |
||
968 |
HRESULT WINAPI QAxClientSite::GetExtendedControl(IDispatch** ppDisp) |
|
969 |
{ |
|
970 |
if (!ppDisp) |
|
971 |
return E_POINTER; |
|
972 |
||
973 |
*ppDisp = 0; |
|
974 |
return E_NOTIMPL; |
|
975 |
} |
|
976 |
||
977 |
HRESULT WINAPI QAxClientSite::TransformCoords(POINTL* /*pPtlHimetric*/, POINTF* /*pPtfContainer*/, DWORD /*dwFlags*/) |
|
978 |
{ |
|
979 |
return S_OK; |
|
980 |
} |
|
981 |
||
982 |
HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, DWORD /*grfModifiers*/) |
|
983 |
{ |
|
984 |
if (lpMsg->message == WM_KEYDOWN && !lpMsg->wParam) |
|
985 |
return S_OK; |
|
986 |
||
987 |
bool ActiveQtDetected = false; |
|
988 |
bool fromInProcServer = false; |
|
989 |
#ifdef GWLP_USERDATA |
|
990 |
LONG_PTR serverType = GetWindowLongPtr(lpMsg->hwnd, GWLP_USERDATA); |
|
991 |
#else |
|
992 |
LONG serverType = GetWindowLong(lpMsg->hwnd, GWL_USERDATA); |
|
993 |
#endif |
|
994 |
if (serverType == QAX_INPROC_SERVER) { |
|
995 |
ActiveQtDetected = true; |
|
996 |
fromInProcServer = true; |
|
997 |
} else if (serverType == QAX_OUTPROC_SERVER) { |
|
998 |
ActiveQtDetected = true; |
|
999 |
fromInProcServer = false; |
|
1000 |
} |
|
1001 |
||
1002 |
eventTranslated = false; |
|
1003 |
if (!ActiveQtDetected || !fromInProcServer) { |
|
1004 |
// if the request is coming from an out-of-proc server or a non ActiveQt server, |
|
1005 |
// we send the message to the host window. This will make sure this key event |
|
1006 |
// comes to Qt for processing. |
|
1007 |
SendMessage(host->winId(), lpMsg->message, lpMsg->wParam, lpMsg->lParam); |
|
1008 |
if (ActiveQtDetected && !fromInProcServer) { |
|
1009 |
// ActiveQt based servers will need further processing of the event |
|
1010 |
// (eg. <SPACE> key for a checkbox), so we return false. |
|
1011 |
return S_FALSE; |
|
1012 |
} |
|
1013 |
} |
|
1014 |
// ActiveQt based in-processes-servers will handle the event properly, so |
|
1015 |
// we dont need to send this key event to the host. |
|
1016 |
return S_OK; |
|
1017 |
} |
|
1018 |
||
1019 |
HRESULT WINAPI QAxClientSite::OnFocus(BOOL bGotFocus) |
|
1020 |
{ |
|
1021 |
AX_DEBUG(QAxClientSite::OnFocus); |
|
1022 |
if (host) { |
|
1023 |
host->hasFocus = bGotFocus; |
|
1024 |
qApp->removeEventFilter(host); |
|
1025 |
if (bGotFocus) |
|
1026 |
qApp->installEventFilter(host); |
|
1027 |
} |
|
1028 |
return S_OK; |
|
1029 |
} |
|
1030 |
||
1031 |
HRESULT WINAPI QAxClientSite::ShowPropertyFrame() |
|
1032 |
{ |
|
1033 |
return E_NOTIMPL; |
|
1034 |
} |
|
1035 |
||
1036 |
//**** IOleWindow |
|
1037 |
HRESULT WINAPI QAxClientSite::GetWindow(HWND *phwnd) |
|
1038 |
{ |
|
1039 |
if (!phwnd) |
|
1040 |
return E_POINTER; |
|
1041 |
||
1042 |
*phwnd = host->winId(); |
|
1043 |
return S_OK; |
|
1044 |
} |
|
1045 |
||
1046 |
HRESULT WINAPI QAxClientSite::ContextSensitiveHelp(BOOL fEnterMode) |
|
1047 |
{ |
|
1048 |
if (fEnterMode) |
|
1049 |
QWhatsThis::enterWhatsThisMode(); |
|
1050 |
else |
|
1051 |
QWhatsThis::leaveWhatsThisMode(); |
|
1052 |
||
1053 |
return S_OK; |
|
1054 |
} |
|
1055 |
||
1056 |
//**** IOleInPlaceSite |
|
1057 |
HRESULT WINAPI QAxClientSite::CanInPlaceActivate() |
|
1058 |
{ |
|
1059 |
AX_DEBUG(QAxClientSite::CanInPlaceActivate); |
|
1060 |
return S_OK; |
|
1061 |
} |
|
1062 |
||
1063 |
HRESULT WINAPI QAxClientSite::OnInPlaceActivate() |
|
1064 |
{ |
|
1065 |
AX_DEBUG(QAxClientSite::OnInPlaceActivate); |
|
1066 |
#if !defined(Q_OS_WINCE) |
|
1067 |
OleLockRunning(m_spOleObject, true, false); |
|
1068 |
#endif |
|
1069 |
if (!m_spInPlaceObject) { |
|
1070 |
/* ### disabled for now |
|
1071 |
m_spOleObject->QueryInterface(IID_IOleInPlaceObjectWindowless, (void**) &m_spInPlaceObject); |
|
1072 |
*/ |
|
1073 |
if (m_spInPlaceObject) { |
|
1074 |
inPlaceObjectWindowless = true; |
|
1075 |
} else { |
|
1076 |
inPlaceObjectWindowless = false; |
|
1077 |
m_spOleObject->QueryInterface(IID_IOleInPlaceObject, (void**) &m_spInPlaceObject); |
|
1078 |
} |
|
1079 |
} |
|
1080 |
||
1081 |
return S_OK; |
|
1082 |
} |
|
1083 |
||
1084 |
HRESULT WINAPI QAxClientSite::OnUIActivate() |
|
1085 |
{ |
|
1086 |
AX_DEBUG(QAxClientSite::OnUIActivate); |
|
1087 |
return S_OK; |
|
1088 |
} |
|
1089 |
||
1090 |
HRESULT WINAPI QAxClientSite::GetWindowContext(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) |
|
1091 |
{ |
|
1092 |
if (!ppFrame || !ppDoc || !lprcPosRect || !lprcClipRect || !lpFrameInfo) |
|
1093 |
return E_POINTER; |
|
1094 |
||
1095 |
QueryInterface(IID_IOleInPlaceFrame, (void**)ppFrame); |
|
1096 |
QueryInterface(IID_IOleInPlaceUIWindow, (void**)ppDoc); |
|
1097 |
||
1098 |
::GetClientRect(host->winId(), lprcPosRect); |
|
1099 |
::GetClientRect(host->winId(), lprcClipRect); |
|
1100 |
||
1101 |
lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO); |
|
1102 |
lpFrameInfo->fMDIApp = false; |
|
1103 |
lpFrameInfo->haccel = 0; |
|
1104 |
lpFrameInfo->cAccelEntries = 0; |
|
1105 |
lpFrameInfo->hwndFrame = widget ? widget->window()->winId() : 0; |
|
1106 |
||
1107 |
return S_OK; |
|
1108 |
} |
|
1109 |
||
1110 |
HRESULT WINAPI QAxClientSite::Scroll(SIZE /*scrollExtant*/) |
|
1111 |
{ |
|
1112 |
return S_FALSE; |
|
1113 |
} |
|
1114 |
||
1115 |
HRESULT WINAPI QAxClientSite::OnUIDeactivate(BOOL) |
|
1116 |
{ |
|
1117 |
AX_DEBUG(QAxClientSite::OnUIDeactivate); |
|
1118 |
if (host && host->hasFocus) { |
|
1119 |
qApp->removeEventFilter(host); |
|
1120 |
host->hasFocus = false; |
|
1121 |
} |
|
1122 |
return S_OK; |
|
1123 |
} |
|
1124 |
||
1125 |
HRESULT WINAPI QAxClientSite::OnInPlaceDeactivate() |
|
1126 |
{ |
|
1127 |
AX_DEBUG(QAxClientSite::OnInPlaceDeactivate); |
|
1128 |
if (m_spInPlaceObject) |
|
1129 |
m_spInPlaceObject->Release(); |
|
1130 |
m_spInPlaceObject = 0; |
|
1131 |
inPlaceObjectWindowless = false; |
|
1132 |
#if !defined(Q_OS_WINCE) |
|
1133 |
OleLockRunning(m_spOleObject, false, false); |
|
1134 |
#endif |
|
1135 |
||
1136 |
return S_OK; |
|
1137 |
} |
|
1138 |
||
1139 |
HRESULT WINAPI QAxClientSite::DiscardUndoState() |
|
1140 |
{ |
|
1141 |
return S_OK; |
|
1142 |
} |
|
1143 |
||
1144 |
HRESULT WINAPI QAxClientSite::DeactivateAndUndo() |
|
1145 |
{ |
|
1146 |
if (m_spInPlaceObject) |
|
1147 |
m_spInPlaceObject->UIDeactivate(); |
|
1148 |
||
1149 |
return S_OK; |
|
1150 |
} |
|
1151 |
||
1152 |
HRESULT WINAPI QAxClientSite::OnPosRectChange(LPCRECT /*lprcPosRect*/) |
|
1153 |
{ |
|
1154 |
AX_DEBUG(QAxClientSite::OnPosRectChange); |
|
1155 |
// ### |
|
1156 |
return S_OK; |
|
1157 |
} |
|
1158 |
||
1159 |
//**** IOleInPlaceFrame |
|
1160 |
#if defined(Q_WS_WINCE) |
|
1161 |
HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/) |
|
1162 |
{ |
|
1163 |
return E_NOTIMPL; |
|
1164 |
#else |
|
1165 |
HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS lpMenuWidths) |
|
1166 |
{ |
|
1167 |
AX_DEBUG(QAxClientSite::InsertMenus); |
|
1168 |
QMenuBar *mb = menuBar; |
|
1169 |
if (!mb) |
|
1170 |
mb = qFindChild<QMenuBar*>(widget->window()); |
|
1171 |
if (!mb) |
|
1172 |
return E_NOTIMPL; |
|
1173 |
menuBar = mb; |
|
1174 |
||
1175 |
QMenu *fileMenu = 0; |
|
1176 |
QMenu *viewMenu = 0; |
|
1177 |
QMenu *windowMenu = 0; |
|
1178 |
QList<QAction*> actions = menuBar->actions(); |
|
1179 |
for (int i = 0; i < actions.count(); ++i) { |
|
1180 |
QAction *action = actions.at(i); |
|
1181 |
QString text = action->text().remove(QLatin1Char('&')); |
|
1182 |
if (text == QLatin1String("File")) { |
|
1183 |
fileMenu = action->menu(); |
|
1184 |
} else if (text == QLatin1String("View")) { |
|
1185 |
viewMenu = action->menu(); |
|
1186 |
} else if (text == QLatin1String("Window")) { |
|
1187 |
windowMenu = action->menu(); |
|
1188 |
} |
|
1189 |
} |
|
1190 |
if (fileMenu) |
|
1191 |
lpMenuWidths->width[0] = fileMenu->actions().count(); |
|
1192 |
if (viewMenu) |
|
1193 |
lpMenuWidths->width[2] = viewMenu->actions().count(); |
|
1194 |
if (windowMenu) |
|
1195 |
lpMenuWidths->width[4] = windowMenu->actions().count(); |
|
1196 |
||
1197 |
return S_OK; |
|
1198 |
#endif |
|
1199 |
} |
|
1200 |
||
1201 |
static int menuItemEntry(HMENU menu, int index, MENUITEMINFO item, QString &text, QPixmap &/*icon*/) |
|
1202 |
{ |
|
1203 |
if (item.fType == MFT_STRING && item.cch) { |
|
1204 |
wchar_t *titlebuf = new wchar_t[item.cch + 1]; |
|
1205 |
item.dwTypeData = titlebuf; |
|
1206 |
item.cch++; |
|
1207 |
::GetMenuItemInfo(menu, index, true, &item); |
|
1208 |
text = QString::fromWCharArray(titlebuf); |
|
1209 |
delete [] titlebuf; |
|
1210 |
return MFT_STRING; |
|
1211 |
} |
|
1212 |
#if 0 |
|
1213 |
else if (item.fType == MFT_BITMAP) { |
|
1214 |
HBITMAP hbm = (HBITMAP)LOWORD(item.hbmpItem); |
|
1215 |
SIZE bmsize; |
|
1216 |
GetBitmapDimensionEx(hbm, &bmsize); |
|
1217 |
QPixmap pixmap(1,1); |
|
1218 |
QSize sz(MAP_LOGHIM_TO_PIX(bmsize.cx, pixmap.logicalDpiX()), |
|
1219 |
MAP_LOGHIM_TO_PIX(bmsize.cy, pixmap.logicalDpiY())); |
|
1220 |
||
1221 |
pixmap.resize(bmsize.cx, bmsize.cy); |
|
1222 |
if (!pixmap.isNull()) { |
|
1223 |
HDC hdc = ::CreateCompatibleDC(pixmap.handle()); |
|
1224 |
::SelectObject(hdc, hbm); |
|
1225 |
BOOL res = ::BitBlt(pixmap.handle(), 0, 0, pixmap.width(), pixmap.height(), hdc, 0, 0, SRCCOPY); |
|
1226 |
::DeleteObject(hdc); |
|
1227 |
} |
|
1228 |
||
1229 |
icon = pixmap; |
|
1230 |
} |
|
1231 |
#endif |
|
1232 |
return -1; |
|
1233 |
} |
|
1234 |
||
1235 |
#if !defined(Q_OS_WINCE) |
|
1236 |
QMenu *QAxClientSite::generatePopup(HMENU subMenu, QWidget *parent) |
|
1237 |
{ |
|
1238 |
QMenu *popup = 0; |
|
1239 |
int count = GetMenuItemCount(subMenu); |
|
1240 |
if (count) |
|
1241 |
popup = new QMenu(parent); |
|
1242 |
for (int i = 0; i < count; ++i) { |
|
1243 |
MENUITEMINFO item; |
|
1244 |
memset(&item, 0, sizeof(MENUITEMINFO)); |
|
1245 |
item.cbSize = sizeof(MENUITEMINFO); |
|
1246 |
item.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU; |
|
1247 |
::GetMenuItemInfo(subMenu, i, true, &item); |
|
1248 |
||
1249 |
QAction *action = 0; |
|
1250 |
QMenu *popupMenu = 0; |
|
1251 |
if (item.fType == MFT_SEPARATOR) { |
|
1252 |
action = popup->addSeparator(); |
|
1253 |
} else { |
|
1254 |
QString text; |
|
1255 |
QPixmap icon; |
|
1256 |
QKeySequence accel; |
|
1257 |
popupMenu = item.hSubMenu ? generatePopup(item.hSubMenu, popup) : 0; |
|
1258 |
int res = menuItemEntry(subMenu, i, item, text, icon); |
|
1259 |
||
1260 |
int lastSep = text.lastIndexOf(QRegExp(QLatin1String("[\\s]"))); |
|
1261 |
if (lastSep != -1) { |
|
1262 |
QString keyString = text.right(text.length() - lastSep); |
|
1263 |
accel = keyString; |
|
1264 |
if ((int)accel) |
|
1265 |
text = text.left(lastSep); |
|
1266 |
} |
|
1267 |
||
1268 |
if (popupMenu) |
|
1269 |
popupMenu->setTitle(text); |
|
1270 |
||
1271 |
switch (res) { |
|
1272 |
case MFT_STRING: |
|
1273 |
if (popupMenu) |
|
1274 |
action = popup->addMenu(popupMenu); |
|
1275 |
else |
|
1276 |
action = popup->addAction(text); |
|
1277 |
break; |
|
1278 |
case MFT_BITMAP: |
|
1279 |
if (popupMenu) |
|
1280 |
action = popup->addMenu(popupMenu); |
|
1281 |
else |
|
1282 |
action = popup->addAction(icon, text); |
|
1283 |
break; |
|
1284 |
} |
|
1285 |
||
1286 |
if (action) { |
|
1287 |
if (int(accel)) |
|
1288 |
action->setShortcut(accel); |
|
1289 |
if (!icon.isNull()) |
|
1290 |
action->setIcon(icon); |
|
1291 |
} |
|
1292 |
} |
|
1293 |
||
1294 |
if (action) { |
|
1295 |
OleMenuItem oleItem(subMenu, item.wID, popupMenu); |
|
1296 |
menuItemMap.insert(action, oleItem); |
|
1297 |
} |
|
1298 |
} |
|
1299 |
return popup; |
|
1300 |
} |
|
1301 |
#endif |
|
1302 |
||
1303 |
#if defined(Q_OS_WINCE) |
|
1304 |
HRESULT WINAPI QAxClientSite::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/) |
|
1305 |
{ |
|
1306 |
return E_NOTIMPL; |
|
1307 |
#else |
|
1308 |
HRESULT WINAPI QAxClientSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) |
|
1309 |
{ |
|
1310 |
AX_DEBUG(QAxClientSite::SetMenu); |
|
1311 |
||
1312 |
if (hmenuShared) { |
|
1313 |
m_menuOwner = hwndActiveObject; |
|
1314 |
QMenuBar *mb = menuBar; |
|
1315 |
if (!mb) |
|
1316 |
mb = qFindChild<QMenuBar*>(widget->window()); |
|
1317 |
if (!mb) |
|
1318 |
return E_NOTIMPL; |
|
1319 |
menuBar = mb; |
|
1320 |
||
1321 |
int count = GetMenuItemCount(hmenuShared); |
|
1322 |
for (int i = 0; i < count; ++i) { |
|
1323 |
MENUITEMINFO item; |
|
1324 |
memset(&item, 0, sizeof(MENUITEMINFO)); |
|
1325 |
item.cbSize = sizeof(MENUITEMINFO); |
|
1326 |
item.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU; |
|
1327 |
::GetMenuItemInfo(hmenuShared, i, true, &item); |
|
1328 |
||
1329 |
QAction *action = 0; |
|
1330 |
QMenu *popupMenu = 0; |
|
1331 |
if (item.fType == MFT_SEPARATOR) { |
|
1332 |
action = menuBar->addSeparator(); |
|
1333 |
} else { |
|
1334 |
QString text; |
|
1335 |
QPixmap icon; |
|
1336 |
popupMenu = item.hSubMenu ? generatePopup(item.hSubMenu, menuBar) : 0; |
|
1337 |
int res = menuItemEntry(hmenuShared, i, item, text, icon); |
|
1338 |
||
1339 |
if (popupMenu) |
|
1340 |
popupMenu->setTitle(text); |
|
1341 |
||
1342 |
switch(res) { |
|
1343 |
case MFT_STRING: |
|
1344 |
if (popupMenu) |
|
1345 |
action = menuBar->addMenu(popupMenu); |
|
1346 |
else |
|
1347 |
action = menuBar->addAction(text); |
|
1348 |
break; |
|
1349 |
case MFT_BITMAP: |
|
1350 |
if (popupMenu) |
|
1351 |
action = menuBar->addMenu(popupMenu); |
|
1352 |
else |
|
1353 |
action = menuBar->addAction(text); |
|
1354 |
break; |
|
1355 |
default: |
|
1356 |
break; |
|
1357 |
} |
|
1358 |
if (action && !icon.isNull()) |
|
1359 |
action->setIcon(icon); |
|
1360 |
} |
|
1361 |
||
1362 |
if (action) { |
|
1363 |
OleMenuItem oleItem(hmenuShared, item.wID, popupMenu); |
|
1364 |
menuItemMap.insert(action, oleItem); |
|
1365 |
} |
|
1366 |
} |
|
1367 |
if (count) { |
|
1368 |
const QMetaObject *mbmo = menuBar->metaObject(); |
|
1369 |
int index = mbmo->indexOfSignal("triggered(QAction*)"); |
|
1370 |
Q_ASSERT(index != -1); |
|
1371 |
menuBar->disconnect(SIGNAL(triggered(QAction*)), host); |
|
1372 |
QMetaObject::connect(menuBar, index, host, index); |
|
1373 |
} |
|
1374 |
} else if (menuBar) { |
|
1375 |
m_menuOwner = 0; |
|
1376 |
QMap<QAction*, OleMenuItem>::Iterator it; |
|
1377 |
for (it = menuItemMap.begin(); it != menuItemMap.end(); ++it) { |
|
1378 |
QAction *action = it.key(); |
|
1379 |
delete action; |
|
1380 |
} |
|
1381 |
menuItemMap.clear(); |
|
1382 |
} |
|
1383 |
||
1384 |
OleSetMenuDescriptor(holemenu, widget ? widget->window()->winId() : 0, m_menuOwner, this, m_spInPlaceActiveObject); |
|
1385 |
return S_OK; |
|
1386 |
#endif |
|
1387 |
} |
|
1388 |
||
1389 |
#if defined(Q_OS_WINCE) |
|
1390 |
int QAxClientSite::qt_metacall(QMetaObject::Call /*call*/, int isignal, void ** /*argv*/) |
|
1391 |
{ |
|
1392 |
return isignal; |
|
1393 |
#else |
|
1394 |
int QAxClientSite::qt_metacall(QMetaObject::Call call, int isignal, void **argv) |
|
1395 |
{ |
|
1396 |
if (!m_spOleObject || call != QMetaObject::InvokeMetaMethod || !menuBar) |
|
1397 |
return isignal; |
|
1398 |
||
1399 |
if (isignal != menuBar->metaObject()->indexOfSignal("triggered(QAction*)")) |
|
1400 |
return isignal; |
|
1401 |
||
1402 |
QAction *action = *(QAction**)argv[1]; |
|
1403 |
// ### |
|
1404 |
||
1405 |
OleMenuItem oleItem = menuItemMap.value(action); |
|
1406 |
if (oleItem.hMenu) |
|
1407 |
::PostMessage(m_menuOwner, WM_COMMAND, oleItem.id, 0); |
|
1408 |
return -1; |
|
1409 |
#endif |
|
1410 |
} |
|
1411 |
||
1412 |
||
1413 |
HRESULT WINAPI QAxClientSite::RemoveMenus(HMENU /*hmenuShared*/) |
|
1414 |
{ |
|
1415 |
#if defined(Q_OS_WINCE) |
|
1416 |
return E_NOTIMPL; |
|
1417 |
#else |
|
1418 |
AX_DEBUG(QAxClientSite::RemoveMenus); |
|
1419 |
QMap<QAction*, OleMenuItem>::Iterator it; |
|
1420 |
for (it = menuItemMap.begin(); it != menuItemMap.end(); ++it) { |
|
1421 |
QAction *action = it.key(); |
|
1422 |
action->setVisible(false); |
|
1423 |
delete action; |
|
1424 |
} |
|
1425 |
menuItemMap.clear(); |
|
1426 |
return S_OK; |
|
1427 |
#endif |
|
1428 |
} |
|
1429 |
||
1430 |
HRESULT WINAPI QAxClientSite::SetStatusText(LPCOLESTR pszStatusText) |
|
1431 |
{ |
|
1432 |
QStatusTipEvent tip(QString::fromWCharArray(pszStatusText)); |
|
1433 |
QApplication::sendEvent(widget, &tip); |
|
1434 |
return S_OK; |
|
1435 |
} |
|
1436 |
||
1437 |
extern Q_GUI_EXPORT bool qt_win_ignoreNextMouseReleaseEvent; |
|
1438 |
||
1439 |
HRESULT WINAPI QAxClientSite::EnableModeless(BOOL fEnable) |
|
1440 |
{ |
|
1441 |
EnableWindow(host->window()->winId(), fEnable); |
|
1442 |
||
1443 |
if (!fEnable) { |
|
1444 |
if (!QApplicationPrivate::isBlockedByModal(host)) |
|
1445 |
QApplicationPrivate::enterModal(host); |
|
1446 |
} else { |
|
1447 |
if (QApplicationPrivate::isBlockedByModal(host)) |
|
1448 |
QApplicationPrivate::leaveModal(host); |
|
1449 |
} |
|
1450 |
qt_win_ignoreNextMouseReleaseEvent = false; |
|
1451 |
return S_OK; |
|
1452 |
} |
|
1453 |
||
1454 |
HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, WORD grfModifiers) |
|
1455 |
{ |
|
1456 |
return TranslateAccelerator(lpMsg, (DWORD)grfModifiers); |
|
1457 |
} |
|
1458 |
||
1459 |
//**** IOleInPlaceUIWindow |
|
1460 |
HRESULT WINAPI QAxClientSite::GetBorder(LPRECT lprectBorder) |
|
1461 |
{ |
|
1462 |
#ifndef QAX_SUPPORT_BORDERSPACE |
|
1463 |
Q_UNUSED(lprectBorder); |
|
1464 |
return INPLACE_E_NOTOOLSPACE; |
|
1465 |
#else |
|
1466 |
AX_DEBUG(QAxClientSite::GetBorder); |
|
1467 |
||
1468 |
QMainWindow *mw = qobject_cast<QMainWindow*>(widget->window()); |
|
1469 |
if (!mw) |
|
1470 |
return INPLACE_E_NOTOOLSPACE; |
|
1471 |
||
1472 |
RECT border = { 0,0, 300, 200 }; |
|
1473 |
*lprectBorder = border; |
|
1474 |
return S_OK; |
|
1475 |
#endif |
|
1476 |
} |
|
1477 |
||
1478 |
HRESULT WINAPI QAxClientSite::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/) |
|
1479 |
{ |
|
1480 |
#ifndef QAX_SUPPORT_BORDERSPACE |
|
1481 |
return INPLACE_E_NOTOOLSPACE; |
|
1482 |
#else |
|
1483 |
AX_DEBUG(QAxClientSite::RequestBorderSpace); |
|
1484 |
||
1485 |
QMainWindow *mw = qobject_cast<QMainWindow*>(widget->window()); |
|
1486 |
if (!mw) |
|
1487 |
return INPLACE_E_NOTOOLSPACE; |
|
1488 |
||
1489 |
return S_OK; |
|
1490 |
#endif |
|
1491 |
} |
|
1492 |
||
1493 |
HRESULT WINAPI QAxClientSite::SetBorderSpace(LPCBORDERWIDTHS pborderwidths) |
|
1494 |
{ |
|
1495 |
#ifndef QAX_SUPPORT_BORDERSPACE |
|
1496 |
Q_UNUSED(pborderwidths); |
|
1497 |
return OLE_E_INVALIDRECT; |
|
1498 |
#else |
|
1499 |
AX_DEBUG(QAxClientSite::SetBorderSpace); |
|
1500 |
||
1501 |
// object has no toolbars and wants container toolbars to remain |
|
1502 |
if (!pborderwidths) |
|
1503 |
return S_OK; |
|
1504 |
||
1505 |
QMainWindow *mw = qobject_cast<QMainWindow*>(widget->window()); |
|
1506 |
if (!mw) |
|
1507 |
return OLE_E_INVALIDRECT; |
|
1508 |
||
1509 |
bool removeToolBars = !(pborderwidths->left || pborderwidths->top || pborderwidths->right || pborderwidths->bottom); |
|
1510 |
||
1511 |
// object has toolbars, and wants container to remove toolbars |
|
1512 |
if (removeToolBars) { |
|
1513 |
if (mw) { |
|
1514 |
//### remove our toolbars |
|
1515 |
} |
|
1516 |
} |
|
1517 |
||
1518 |
if (pborderwidths->left) { |
|
1519 |
QDockWidget *left = new QDockWidget(mw); |
|
1520 |
left->setFixedWidth(pborderwidths->left); |
|
1521 |
mw->addDockWidget(Qt::LeftDockWidgetArea, left); |
|
1522 |
left->show(); |
|
1523 |
} |
|
1524 |
if (pborderwidths->top) { |
|
1525 |
QDockWidget *top = new QDockWidget(mw); |
|
1526 |
top->setFixedHeight(pborderwidths->top); |
|
1527 |
mw->addDockWidget(Qt::TopDockWidgetArea, top); |
|
1528 |
top->show(); |
|
1529 |
} |
|
1530 |
||
1531 |
return S_OK; |
|
1532 |
#endif |
|
1533 |
} |
|
1534 |
||
1535 |
HRESULT WINAPI QAxClientSite::SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) |
|
1536 |
{ |
|
1537 |
AX_DEBUG(QAxClientSite::SetActiveObject); |
|
1538 |
||
1539 |
Q_UNUSED(pszObjName); |
|
1540 |
// we are ignoring the name of the object, as suggested by MSDN documentation |
|
1541 |
// for IOleInPlaceUIWindow::SetActiveObject(). |
|
1542 |
||
1543 |
if (m_spInPlaceActiveObject) { |
|
1544 |
if (!inPlaceModelessEnabled) |
|
1545 |
m_spInPlaceActiveObject->EnableModeless(true); |
|
1546 |
inPlaceModelessEnabled = true; |
|
1547 |
m_spInPlaceActiveObject->Release(); |
|
1548 |
} |
|
1549 |
||
1550 |
m_spInPlaceActiveObject = pActiveObject; |
|
1551 |
if (m_spInPlaceActiveObject) |
|
1552 |
m_spInPlaceActiveObject->AddRef(); |
|
1553 |
||
1554 |
return S_OK; |
|
1555 |
} |
|
1556 |
||
1557 |
//**** IOleDocumentSite |
|
1558 |
HRESULT WINAPI QAxClientSite::ActivateMe(IOleDocumentView *pViewToActivate) |
|
1559 |
{ |
|
1560 |
AX_DEBUG(QAxClientSite::ActivateMe); |
|
1561 |
||
1562 |
if (m_spActiveView) |
|
1563 |
m_spActiveView->Release(); |
|
1564 |
m_spActiveView = 0; |
|
1565 |
||
1566 |
if (!pViewToActivate) { |
|
1567 |
IOleDocument *document = 0; |
|
1568 |
m_spOleObject->QueryInterface(IID_IOleDocument, (void**)&document); |
|
1569 |
if (!document) |
|
1570 |
return E_FAIL; |
|
1571 |
||
1572 |
document->CreateView(this, 0, 0, &pViewToActivate); |
|
1573 |
||
1574 |
document->Release(); |
|
1575 |
if (!pViewToActivate) |
|
1576 |
return E_OUTOFMEMORY; |
|
1577 |
} else { |
|
1578 |
pViewToActivate->SetInPlaceSite(this); |
|
1579 |
} |
|
1580 |
||
1581 |
m_spActiveView = pViewToActivate; |
|
1582 |
m_spActiveView->AddRef(); |
|
1583 |
||
1584 |
m_spActiveView->UIActivate(TRUE); |
|
1585 |
||
1586 |
RECT rect; |
|
1587 |
GetClientRect(widget->winId(), &rect); |
|
1588 |
m_spActiveView->SetRect(&rect); |
|
1589 |
m_spActiveView->Show(TRUE); |
|
1590 |
||
1591 |
return S_OK; |
|
1592 |
} |
|
1593 |
||
1594 |
QSize QAxClientSite::minimumSizeHint() const |
|
1595 |
{ |
|
1596 |
if (!m_spOleObject) |
|
1597 |
return QSize(); |
|
1598 |
||
1599 |
SIZE sz = { 0, 0 }; |
|
1600 |
m_spOleObject->SetExtent(DVASPECT_CONTENT, &sz); |
|
1601 |
HRESULT res = m_spOleObject->GetExtent(DVASPECT_CONTENT, &sz); |
|
1602 |
if (SUCCEEDED(res)) { |
|
1603 |
return QSize(MAP_LOGHIM_TO_PIX(sz.cx, widget->logicalDpiX()), |
|
1604 |
MAP_LOGHIM_TO_PIX(sz.cy, widget->logicalDpiY())); |
|
1605 |
} |
|
1606 |
return QSize(); |
|
1607 |
} |
|
1608 |
||
1609 |
void QAxClientSite::windowActivationChange() |
|
1610 |
{ |
|
1611 |
AX_DEBUG(QAxClientSite::windowActivationChange); |
|
1612 |
||
1613 |
if (m_spInPlaceActiveObject && widget) { |
|
1614 |
QWidget *modal = QApplication::activeModalWidget(); |
|
1615 |
if (modal && inPlaceModelessEnabled) { |
|
1616 |
m_spInPlaceActiveObject->EnableModeless(false); |
|
1617 |
inPlaceModelessEnabled = false; |
|
1618 |
} else if (!inPlaceModelessEnabled) { |
|
1619 |
m_spInPlaceActiveObject->EnableModeless(true); |
|
1620 |
inPlaceModelessEnabled = true; |
|
1621 |
} |
|
1622 |
m_spInPlaceActiveObject->OnFrameWindowActivate(widget->isActiveWindow()); |
|
1623 |
} |
|
1624 |
} |
|
1625 |
||
1626 |
||
1627 |
//**** QWidget |
|
1628 |
||
1629 |
QAxHostWidget::QAxHostWidget(QWidget *parent, QAxClientSite *ax) |
|
1630 |
: QWidget(parent), setFocusTimer(0), hasFocus(false), axhost(ax) |
|
1631 |
{ |
|
1632 |
setAttribute(Qt::WA_NoBackground); |
|
1633 |
setAttribute(Qt::WA_NoSystemBackground); |
|
1634 |
setAttribute(Qt::WA_OpaquePaintEvent); |
|
1635 |
setAttribute(Qt::WA_PaintOnScreen); |
|
1636 |
||
1637 |
setObjectName(parent->objectName() + QLatin1String(" - QAxHostWidget")); |
|
1638 |
} |
|
1639 |
||
1640 |
QAxHostWidget::~QAxHostWidget() |
|
1641 |
{ |
|
1642 |
if (axhost) |
|
1643 |
axhost->reset(this); |
|
1644 |
} |
|
1645 |
||
1646 |
int QAxHostWidget::qt_metacall(QMetaObject::Call call, int isignal, void **argv) |
|
1647 |
{ |
|
1648 |
if (axhost) |
|
1649 |
return axhost->qt_metacall(call, isignal, argv); |
|
1650 |
return -1; |
|
1651 |
} |
|
1652 |
||
1653 |
void* QAxHostWidget::qt_metacast(const char *clname) |
|
1654 |
{ |
|
1655 |
if (!clname) return 0; |
|
1656 |
if (!qstrcmp(clname,"QAxHostWidget")) |
|
1657 |
return static_cast<void*>(const_cast< QAxHostWidget*>(this)); |
|
1658 |
return QWidget::qt_metacast(clname); |
|
1659 |
} |
|
1660 |
||
1661 |
QSize QAxHostWidget::sizeHint() const |
|
1662 |
{ |
|
1663 |
return axhost ? axhost->sizeHint() : QWidget::sizeHint(); |
|
1664 |
} |
|
1665 |
||
1666 |
QSize QAxHostWidget::minimumSizeHint() const |
|
1667 |
{ |
|
1668 |
QSize size; |
|
1669 |
if (axhost) |
|
1670 |
size = axhost->minimumSizeHint(); |
|
1671 |
if (size.isValid()) |
|
1672 |
return size; |
|
1673 |
return QWidget::minimumSizeHint(); |
|
1674 |
} |
|
1675 |
||
1676 |
void QAxHostWidget::resizeObject() |
|
1677 |
{ |
|
1678 |
if (!axhost) |
|
1679 |
return; |
|
1680 |
||
1681 |
// document server - talk to view? |
|
1682 |
if (axhost->m_spActiveView) { |
|
1683 |
RECT rect; |
|
1684 |
GetClientRect(winId(), &rect); |
|
1685 |
axhost->m_spActiveView->SetRect(&rect); |
|
1686 |
||
1687 |
return; |
|
1688 |
} |
|
1689 |
||
1690 |
SIZEL hmSize; |
|
1691 |
hmSize.cx = MAP_PIX_TO_LOGHIM(width(), logicalDpiX()); |
|
1692 |
hmSize.cy = MAP_PIX_TO_LOGHIM(height(), logicalDpiY()); |
|
1693 |
||
1694 |
if (axhost->m_spOleObject) |
|
1695 |
axhost->m_spOleObject->SetExtent(DVASPECT_CONTENT, &hmSize); |
|
1696 |
if (axhost->m_spInPlaceObject) { |
|
1697 |
RECT rcPos = { x(), y(), x()+width(), y()+height() }; |
|
1698 |
axhost->m_spInPlaceObject->SetObjectRects(&rcPos, &rcPos); |
|
1699 |
} |
|
1700 |
} |
|
1701 |
||
1702 |
void QAxHostWidget::resizeEvent(QResizeEvent *) |
|
1703 |
{ |
|
1704 |
resizeObject(); |
|
1705 |
} |
|
1706 |
||
1707 |
void QAxHostWidget::showEvent(QShowEvent *) |
|
1708 |
{ |
|
1709 |
resizeObject(); |
|
1710 |
} |
|
1711 |
||
1712 |
bool QAxHostWidget::winEvent(MSG *msg, long *result) |
|
1713 |
{ |
|
1714 |
if (axhost && axhost->inPlaceObjectWindowless) { |
|
1715 |
Q_ASSERT(axhost->m_spInPlaceObject); |
|
1716 |
IOleInPlaceObjectWindowless *windowless = (IOleInPlaceObjectWindowless*)axhost->m_spInPlaceObject; |
|
1717 |
Q_ASSERT(windowless); |
|
1718 |
LRESULT lres; |
|
1719 |
HRESULT hres = windowless->OnWindowMessage(msg->message, msg->wParam, msg->lParam, &lres); |
|
1720 |
if (hres == S_OK) |
|
1721 |
return true; |
|
1722 |
} |
|
1723 |
return QWidget::winEvent(msg, result); |
|
1724 |
} |
|
1725 |
||
1726 |
bool QAxHostWidget::event(QEvent *e) |
|
1727 |
{ |
|
1728 |
switch (e->type()) { |
|
1729 |
case QEvent::Timer: |
|
1730 |
if (axhost && ((QTimerEvent*)e)->timerId() == setFocusTimer) { |
|
1731 |
killTimer(setFocusTimer); |
|
1732 |
setFocusTimer = 0; |
|
1733 |
RECT rcPos = { x(), y(), x()+size().width(), y()+size().height() }; |
|
1734 |
axhost->m_spOleObject->DoVerb(OLEIVERB_UIACTIVATE, 0, (IOleClientSite*)axhost, 0, winId(), &rcPos); |
|
1735 |
if (axhost->m_spActiveView) |
|
1736 |
axhost->m_spActiveView->UIActivate(TRUE); |
|
1737 |
} |
|
1738 |
break; |
|
1739 |
case QEvent::WindowBlocked: |
|
1740 |
if (IsWindowEnabled(winId())) { |
|
1741 |
EnableWindow(winId(), false); |
|
1742 |
if (axhost && axhost->m_spInPlaceActiveObject) { |
|
1743 |
axhost->inPlaceModelessEnabled = false; |
|
1744 |
axhost->m_spInPlaceActiveObject->EnableModeless(false); |
|
1745 |
} |
|
1746 |
} |
|
1747 |
break; |
|
1748 |
case QEvent::WindowUnblocked: |
|
1749 |
if (!IsWindowEnabled(winId())) { |
|
1750 |
EnableWindow(winId(), true); |
|
1751 |
if (axhost && axhost->m_spInPlaceActiveObject) { |
|
1752 |
axhost->inPlaceModelessEnabled = true; |
|
1753 |
axhost->m_spInPlaceActiveObject->EnableModeless(true); |
|
1754 |
} |
|
1755 |
} |
|
1756 |
break; |
|
1757 |
default: |
|
1758 |
break; |
|
1759 |
} |
|
1760 |
||
1761 |
return QWidget::event(e); |
|
1762 |
} |
|
1763 |
||
1764 |
bool QAxHostWidget::eventFilter(QObject *o, QEvent *e) |
|
1765 |
{ |
|
1766 |
// focus goes to Qt while ActiveX still has it - deactivate |
|
1767 |
QWidget *newFocus = qobject_cast<QWidget*>(o); |
|
1768 |
if (e->type() == QEvent::FocusIn && hasFocus |
|
1769 |
&& newFocus && newFocus->window() == window()) { |
|
1770 |
if (axhost && axhost->m_spInPlaceActiveObject && axhost->m_spInPlaceObject) |
|
1771 |
axhost->m_spInPlaceObject->UIDeactivate(); |
|
1772 |
qApp->removeEventFilter(this); |
|
1773 |
} |
|
1774 |
||
1775 |
return QWidget::eventFilter(o, e); |
|
1776 |
} |
|
1777 |
||
1778 |
void QAxHostWidget::focusInEvent(QFocusEvent *e) |
|
1779 |
{ |
|
1780 |
QWidget::focusInEvent(e); |
|
1781 |
||
1782 |
if (!axhost || !axhost->m_spOleObject) |
|
1783 |
return; |
|
1784 |
||
1785 |
// this is called by QWidget::setFocus which calls ::SetFocus on "this", |
|
1786 |
// so we have to UIActivate the control after all that had happend. |
|
1787 |
AX_DEBUG(Setting focus on in-place object); |
|
1788 |
setFocusTimer = startTimer(0); |
|
1789 |
} |
|
1790 |
||
1791 |
void QAxHostWidget::focusOutEvent(QFocusEvent *e) |
|
1792 |
{ |
|
1793 |
QWidget::focusOutEvent(e); |
|
1794 |
if (setFocusTimer) { |
|
1795 |
killTimer(setFocusTimer); |
|
1796 |
setFocusTimer = 0; |
|
1797 |
} |
|
1798 |
if (e->reason() == Qt::PopupFocusReason || e->reason() == Qt::MenuBarFocusReason) |
|
1799 |
return; |
|
1800 |
||
1801 |
if (!axhost || !axhost->m_spInPlaceActiveObject || !axhost->m_spInPlaceObject) |
|
1802 |
return; |
|
1803 |
||
1804 |
AX_DEBUG(Deactivating in-place object); |
|
1805 |
axhost->m_spInPlaceObject->UIDeactivate(); |
|
1806 |
} |
|
1807 |
||
1808 |
||
1809 |
void QAxHostWidget::paintEvent(QPaintEvent*) |
|
1810 |
{ |
|
1811 |
if (!QPainter::redirected(this)) |
|
1812 |
return; |
|
1813 |
||
1814 |
IViewObject *view = 0; |
|
1815 |
if (axhost) |
|
1816 |
axhost->widget->queryInterface(IID_IViewObject, (void**)&view); |
|
1817 |
if (!view) |
|
1818 |
return; |
|
1819 |
||
1820 |
// somebody tries to grab us! |
|
1821 |
QPixmap pm(size()); |
|
1822 |
pm.fill(); |
|
1823 |
||
1824 |
HBITMAP hBmp = pm.toWinHBITMAP(); |
|
1825 |
HDC hBmp_hdc = CreateCompatibleDC(qt_win_display_dc()); |
|
1826 |
HGDIOBJ old_hBmp = SelectObject(hBmp_hdc, hBmp); |
|
1827 |
||
1828 |
RECTL bounds; |
|
1829 |
bounds.left = 0; |
|
1830 |
bounds.right = pm.width(); |
|
1831 |
bounds.top = 0; |
|
1832 |
bounds.bottom = pm.height(); |
|
1833 |
||
1834 |
view->Draw(DVASPECT_CONTENT, -1, 0, 0, 0, hBmp_hdc, &bounds, 0, 0 /*fptr*/, 0); |
|
1835 |
view->Release(); |
|
1836 |
||
1837 |
QPainter painter(this); |
|
1838 |
painter.drawPixmap(0, 0, QPixmap::fromWinHBITMAP(hBmp)); |
|
1839 |
||
1840 |
SelectObject(hBmp_hdc, old_hBmp); |
|
1841 |
DeleteObject(hBmp); |
|
1842 |
DeleteDC(hBmp_hdc); |
|
1843 |
} |
|
1844 |
||
1845 |
/*! |
|
1846 |
\class QAxWidget |
|
1847 |
\brief The QAxWidget class is a QWidget that wraps an ActiveX control. |
|
1848 |
||
1849 |
\inmodule QAxContainer |
|
1850 |
||
1851 |
A QAxWidget can be instantiated as an empty object, with the name |
|
1852 |
of the ActiveX control it should wrap, or with an existing |
|
1853 |
interface pointer to the ActiveX control. The ActiveX control's |
|
1854 |
properties, methods and events which only use QAxBase |
|
1855 |
supported data types, become available as Qt properties, |
|
1856 |
slots and signals. The base class QAxBase provides an API to |
|
1857 |
access the ActiveX directly through the \c IUnknown pointer. |
|
1858 |
||
1859 |
QAxWidget is a QWidget and can mostly be used as such, e.g. it can be |
|
1860 |
organized in a widget hierarchy and layouts or act as an event filter. |
|
1861 |
Standard widget properties, e.g. \link QWidget::enabled |
|
1862 |
enabled \endlink are supported, but it depends on the ActiveX |
|
1863 |
control to implement support for ambient properties like e.g. |
|
1864 |
palette or font. QAxWidget tries to provide the necessary hints. |
|
1865 |
||
1866 |
However, you cannot reimplement Qt-specific event handlers like |
|
1867 |
mousePressEvent or keyPressEvent and expect them to be called reliably. |
|
1868 |
The embedded control covers the QAxWidget completely, and usually |
|
1869 |
handles the user interface itself. Use control-specific APIs (i.e. listen |
|
1870 |
to the signals of the control), or use standard COM techniques like |
|
1871 |
window procedure subclassing. |
|
1872 |
||
1873 |
QAxWidget also inherits most of its ActiveX-related functionality |
|
1874 |
from QAxBase, notably dynamicCall() and querySubObject(). |
|
1875 |
||
1876 |
\warning |
|
1877 |
You can subclass QAxWidget, but you cannot use the \c Q_OBJECT macro |
|
1878 |
in the subclass (the generated moc-file will not compile), so you |
|
1879 |
cannot add further signals, slots or properties. This limitation |
|
1880 |
is due to the metaobject information generated in runtime. To work |
|
1881 |
around this problem, aggregate the QAxWidget as a member of the |
|
1882 |
QObject subclass. |
|
1883 |
||
1884 |
\sa QAxBase, QAxObject, QAxScript, {ActiveQt Framework} |
|
1885 |
*/ |
|
1886 |
||
1887 |
/*! |
|
1888 |
Creates an empty QAxWidget widget and propagates \a parent |
|
1889 |
and \a f to the QWidget constructor. To initialize a control, |
|
1890 |
call setControl(). |
|
1891 |
*/ |
|
1892 |
QAxWidget::QAxWidget(QWidget *parent, Qt::WindowFlags f) |
|
1893 |
: QWidget(parent, f), container(0) |
|
1894 |
{ |
|
1895 |
} |
|
1896 |
||
1897 |
/*! |
|
1898 |
Creates an QAxWidget widget and initializes the ActiveX control \a c. |
|
1899 |
\a parent and \a f are propagated to the QWidget contructor. |
|
1900 |
||
1901 |
\sa setControl() |
|
1902 |
*/ |
|
1903 |
QAxWidget::QAxWidget(const QString &c, QWidget *parent, Qt::WindowFlags f) |
|
1904 |
: QWidget(parent, f), container(0) |
|
1905 |
{ |
|
1906 |
setControl(c); |
|
1907 |
} |
|
1908 |
||
1909 |
/*! |
|
1910 |
Creates a QAxWidget that wraps the COM object referenced by \a iface. |
|
1911 |
\a parent and \a f are propagated to the QWidget contructor. |
|
1912 |
*/ |
|
1913 |
QAxWidget::QAxWidget(IUnknown *iface, QWidget *parent, Qt::WindowFlags f) |
|
1914 |
: QWidget(parent, f), QAxBase(iface), container(0) |
|
1915 |
{ |
|
1916 |
} |
|
1917 |
||
1918 |
/*! |
|
1919 |
Shuts down the ActiveX control and destroys the QAxWidget widget, |
|
1920 |
cleaning up all allocated resources. |
|
1921 |
||
1922 |
\sa clear() |
|
1923 |
*/ |
|
1924 |
QAxWidget::~QAxWidget() |
|
1925 |
{ |
|
1926 |
if (container) |
|
1927 |
container->reset(this); |
|
1928 |
clear(); |
|
1929 |
} |
|
1930 |
||
1931 |
/*! |
|
1932 |
\since 4.2 |
|
1933 |
||
1934 |
Calls QAxBase::initialize(\a ptr), and embeds the control in this |
|
1935 |
widget by calling createHostWindow(false) if successful. |
|
1936 |
||
1937 |
To initialize the control before it is activated, reimplement this |
|
1938 |
function and add your initialization code before you call |
|
1939 |
createHostWindow(true). |
|
1940 |
*/ |
|
1941 |
bool QAxWidget::initialize(IUnknown **ptr) |
|
1942 |
{ |
|
1943 |
if (!QAxBase::initialize(ptr)) |
|
1944 |
return false; |
|
1945 |
||
1946 |
return createHostWindow(false); // assume that control is not initialized |
|
1947 |
} |
|
1948 |
||
1949 |
/*! |
|
1950 |
Creates the client site for the ActiveX control, and returns true if |
|
1951 |
the control could be embedded successfully, otherwise returns false. |
|
1952 |
If \a initialized is true the control has already been initialized. |
|
1953 |
||
1954 |
This function is called by initialize(). If you reimplement initialize |
|
1955 |
to customize the actual control instantiation, call this function in your |
|
1956 |
reimplementation to have the control embedded by the default client side. |
|
1957 |
Creates the client site for the ActiveX control, and returns true if |
|
1958 |
the control could be embedded successfully, otherwise returns false. |
|
1959 |
*/ |
|
1960 |
bool QAxWidget::createHostWindow(bool initialized) |
|
1961 |
{ |
|
1962 |
return createHostWindow(initialized, QByteArray()); |
|
1963 |
} |
|
1964 |
||
1965 |
/*! |
|
1966 |
\since 4.4 |
|
1967 |
||
1968 |
Creates the client site for the ActiveX control, and returns true if |
|
1969 |
the control could be embedded successfully, otherwise returns false. |
|
1970 |
If \a initialized is false the control will be initialized using the |
|
1971 |
\a data. The control will be initialized through either IPersistStreamInit |
|
1972 |
or IPersistStorage interface. |
|
1973 |
||
1974 |
If the control needs to be initialized using custom data, call this function |
|
1975 |
in your reimplementation of initialize(). This function is not called by |
|
1976 |
the default implementation of initialize(). |
|
1977 |
*/ |
|
1978 |
bool QAxWidget::createHostWindow(bool initialized, const QByteArray &data) |
|
1979 |
{ |
|
1980 |
#ifdef QT3_SUPPORT |
|
1981 |
QApplication::sendPostedEvents(0, QEvent::ChildInserted); |
|
1982 |
#endif |
|
1983 |
||
1984 |
container = new QAxClientSite(this); |
|
1985 |
container->activateObject(initialized, data); |
|
1986 |
||
1987 |
#if !defined(Q_OS_WINCE) |
|
1988 |
ATOM filter_ref = FindAtom(qaxatom); |
|
1989 |
#endif |
|
1990 |
if (!filter_ref) |
|
1991 |
previous_filter = QAbstractEventDispatcher::instance()->setEventFilter(axc_FilterProc); |
|
1992 |
#if !defined(Q_OS_WINCE) |
|
1993 |
AddAtom(qaxatom); |
|
1994 |
#else |
|
1995 |
++filter_ref; |
|
1996 |
#endif |
|
1997 |
||
1998 |
if (parentWidget()) |
|
1999 |
QApplication::postEvent(parentWidget(), new QEvent(QEvent::LayoutRequest)); |
|
2000 |
||
2001 |
return true; |
|
2002 |
} |
|
2003 |
||
2004 |
/*! |
|
2005 |
Reimplement this function when you want to implement additional |
|
2006 |
COM interfaces for the client site of the ActiveX control, or when |
|
2007 |
you want to provide alternative implementations of COM interfaces. |
|
2008 |
Return a new object of a QAxAggregated subclass. |
|
2009 |
||
2010 |
The default implementation returns the null pointer. |
|
2011 |
*/ |
|
2012 |
QAxAggregated *QAxWidget::createAggregate() |
|
2013 |
{ |
|
2014 |
return 0; |
|
2015 |
} |
|
2016 |
||
2017 |
/*! |
|
2018 |
\reimp |
|
2019 |
||
2020 |
Shuts down the ActiveX control. |
|
2021 |
*/ |
|
2022 |
void QAxWidget::clear() |
|
2023 |
{ |
|
2024 |
if (isNull()) |
|
2025 |
return; |
|
2026 |
if (!control().isEmpty()) { |
|
2027 |
#if !defined(Q_OS_WINCE) |
|
2028 |
ATOM filter_ref = FindAtom(qaxatom); |
|
2029 |
if (filter_ref) |
|
2030 |
DeleteAtom(filter_ref); |
|
2031 |
filter_ref = FindAtom(qaxatom); |
|
2032 |
if (!filter_ref) { |
|
2033 |
#else |
|
2034 |
if (!filter_ref && !--filter_ref) { |
|
2035 |
#endif |
|
2036 |
QAbstractEventDispatcher::instance()->setEventFilter(previous_filter); |
|
2037 |
previous_filter = 0; |
|
2038 |
} |
|
2039 |
} |
|
2040 |
||
2041 |
if (container) |
|
2042 |
container->deactivate(); |
|
2043 |
||
2044 |
QAxBase::clear(); |
|
2045 |
setFocusPolicy(Qt::NoFocus); |
|
2046 |
||
2047 |
if (container) { |
|
2048 |
container->releaseAll(); |
|
2049 |
container->Release(); |
|
2050 |
} |
|
2051 |
container = 0; |
|
2052 |
} |
|
2053 |
||
2054 |
/*! |
|
2055 |
\since 4.1 |
|
2056 |
||
2057 |
Requests the ActiveX control to perform the action \a verb. The |
|
2058 |
possible verbs are returned by verbs(). |
|
2059 |
||
2060 |
The function returns true if the object could perform the action, otherwise returns false. |
|
2061 |
*/ |
|
2062 |
bool QAxWidget::doVerb(const QString &verb) |
|
2063 |
{ |
|
2064 |
if (!verbs().contains(verb)) |
|
2065 |
return false; |
|
2066 |
||
2067 |
HRESULT hres = container->doVerb(indexOfVerb(verb)); |
|
2068 |
||
2069 |
return hres == S_OK; |
|
2070 |
} |
|
2071 |
||
2072 |
/*! |
|
2073 |
\fn QObject *QAxWidget::qObject() const |
|
2074 |
\internal |
|
2075 |
*/ |
|
2076 |
||
2077 |
/*! |
|
2078 |
\internal |
|
2079 |
*/ |
|
2080 |
const QMetaObject *QAxWidget::metaObject() const |
|
2081 |
{ |
|
2082 |
return QAxBase::metaObject(); |
|
2083 |
} |
|
2084 |
||
2085 |
/*! |
|
2086 |
\internal |
|
2087 |
*/ |
|
2088 |
const QMetaObject *QAxWidget::parentMetaObject() const |
|
2089 |
{ |
|
2090 |
return &QWidget::staticMetaObject; |
|
2091 |
} |
|
2092 |
||
2093 |
/*! |
|
2094 |
\internal |
|
2095 |
*/ |
|
2096 |
void *QAxWidget::qt_metacast(const char *cname) |
|
2097 |
{ |
|
2098 |
if (!qstrcmp(cname, "QAxWidget")) return (void*)this; |
|
2099 |
if (!qstrcmp(cname, "QAxBase")) return (QAxBase*)this; |
|
2100 |
return QWidget::qt_metacast(cname); |
|
2101 |
} |
|
2102 |
||
2103 |
/*! |
|
2104 |
\internal |
|
2105 |
*/ |
|
2106 |
const char *QAxWidget::className() const |
|
2107 |
{ |
|
2108 |
return "QAxWidget"; |
|
2109 |
} |
|
2110 |
||
2111 |
/*! |
|
2112 |
\internal |
|
2113 |
*/ |
|
2114 |
int QAxWidget::qt_metacall(QMetaObject::Call call, int id, void **v) |
|
2115 |
{ |
|
2116 |
id = QWidget::qt_metacall(call, id, v); |
|
2117 |
if (id < 0) |
|
2118 |
return id; |
|
2119 |
return QAxBase::qt_metacall(call, id, v); |
|
2120 |
} |
|
2121 |
||
2122 |
/*! |
|
2123 |
\reimp |
|
2124 |
*/ |
|
2125 |
QSize QAxWidget::sizeHint() const |
|
2126 |
{ |
|
2127 |
if (container) { |
|
2128 |
QSize sh = container->sizeHint(); |
|
2129 |
if (sh.isValid()) |
|
2130 |
return sh; |
|
2131 |
} |
|
2132 |
||
2133 |
return QWidget::sizeHint(); |
|
2134 |
} |
|
2135 |
||
2136 |
/*! |
|
2137 |
\reimp |
|
2138 |
*/ |
|
2139 |
QSize QAxWidget::minimumSizeHint() const |
|
2140 |
{ |
|
2141 |
if (container) { |
|
2142 |
QSize sh = container->minimumSizeHint(); |
|
2143 |
if (sh.isValid()) |
|
2144 |
return sh; |
|
2145 |
} |
|
2146 |
||
2147 |
return QWidget::minimumSizeHint(); |
|
2148 |
} |
|
2149 |
||
2150 |
/*! |
|
2151 |
\reimp |
|
2152 |
*/ |
|
2153 |
void QAxWidget::changeEvent(QEvent *e) |
|
2154 |
{ |
|
2155 |
if (isNull()) |
|
2156 |
return; |
|
2157 |
||
2158 |
switch (e->type()) { |
|
2159 |
case QEvent::EnabledChange: |
|
2160 |
container->emitAmbientPropertyChange(DISPID_AMBIENT_UIDEAD); |
|
2161 |
break; |
|
2162 |
case QEvent::FontChange: |
|
2163 |
container->emitAmbientPropertyChange(DISPID_AMBIENT_FONT); |
|
2164 |
break; |
|
2165 |
case QEvent::PaletteChange: |
|
2166 |
container->emitAmbientPropertyChange(DISPID_AMBIENT_BACKCOLOR); |
|
2167 |
container->emitAmbientPropertyChange(DISPID_AMBIENT_FORECOLOR); |
|
2168 |
break; |
|
2169 |
case QEvent::ActivationChange: |
|
2170 |
container->windowActivationChange(); |
|
2171 |
break; |
|
2172 |
default: |
|
2173 |
break; |
|
2174 |
} |
|
2175 |
} |
|
2176 |
||
2177 |
/*! |
|
2178 |
\reimp |
|
2179 |
*/ |
|
2180 |
void QAxWidget::resizeEvent(QResizeEvent *) |
|
2181 |
{ |
|
2182 |
if (container) |
|
2183 |
container->resize(size()); |
|
2184 |
} |
|
2185 |
||
2186 |
/*! |
|
2187 |
\reimp |
|
2188 |
*/ |
|
2189 |
void QAxWidget::connectNotify(const char *) |
|
2190 |
{ |
|
2191 |
QAxBase::connectNotify(); |
|
2192 |
} |
|
2193 |
||
2194 |
||
2195 |
/*! |
|
2196 |
Reimplement this function to pass certain key events to the |
|
2197 |
ActiveX control. \a message is the Window message identifier |
|
2198 |
specifying the message type (ie. WM_KEYDOWN), and \a keycode is |
|
2199 |
the virtual keycode (ie. VK_TAB). |
|
2200 |
||
2201 |
If the function returns true the key event is passed on to the |
|
2202 |
ActiveX control, which then either processes the event or passes |
|
2203 |
the event on to Qt. |
|
2204 |
||
2205 |
If the function returns false the processing of the key event is |
|
2206 |
ignored by ActiveQt, ie. the ActiveX control might handle it or |
|
2207 |
not. |
|
2208 |
||
2209 |
The default implementation returns true for the following cases: |
|
2210 |
||
2211 |
\table |
|
2212 |
\header |
|
2213 |
\i WM_SYSKEYDOWN |
|
2214 |
\i WM_SYSKEYUP |
|
2215 |
\i WM_KEYDOWN |
|
2216 |
\row |
|
2217 |
\i All keycodes |
|
2218 |
\i VK_MENU |
|
2219 |
\i VK_TAB, VK_DELETE and all non-arrow-keys in combination with VK_SHIFT, |
|
2220 |
VK_CONTROL or VK_MENU |
|
2221 |
\endtable |
|
2222 |
||
2223 |
This table is the result of experimenting with popular ActiveX controls, |
|
2224 |
ie. Internet Explorer and Microsoft Office applications, but for some |
|
2225 |
controls it might require modification. |
|
2226 |
*/ |
|
2227 |
bool QAxWidget::translateKeyEvent(int message, int keycode) const |
|
2228 |
{ |
|
2229 |
bool translate = false; |
|
2230 |
||
2231 |
switch (message) { |
|
2232 |
case WM_SYSKEYDOWN: |
|
2233 |
translate = true; |
|
2234 |
break; |
|
2235 |
case WM_KEYDOWN: |
|
2236 |
translate = keycode == VK_TAB |
|
2237 |
|| keycode == VK_DELETE; |
|
2238 |
if (!translate) { |
|
2239 |
int state = 0; |
|
2240 |
if (GetKeyState(VK_SHIFT) < 0) |
|
2241 |
state |= 0x01; |
|
2242 |
if (GetKeyState(VK_CONTROL) < 0) |
|
2243 |
state |= 0x02; |
|
2244 |
if (GetKeyState(VK_MENU) < 0) |
|
2245 |
state |= 0x04; |
|
2246 |
if (state) { |
|
2247 |
state = keycode < VK_LEFT || keycode > VK_DOWN; |
|
2248 |
} |
|
2249 |
translate = state; |
|
2250 |
} |
|
2251 |
break; |
|
2252 |
case WM_SYSKEYUP: |
|
2253 |
translate = keycode == VK_MENU; |
|
2254 |
break; |
|
2255 |
} |
|
2256 |
||
2257 |
return translate; |
|
2258 |
} |
|
2259 |
||
2260 |
QT_END_NAMESPACE |
|
2261 |
#endif // QT_NO_WIN_ACTIVEQT |