source: trunk/src/activeqt/container/qaxwidget.cpp@ 1054

Last change on this file since 1054 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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