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

Last change on this file since 158 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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