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

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

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