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

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

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

File size: 65.6 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 EnableWindow(host->window()->winId(), fEnable);
1442
1443 if (!fEnable) {
1444 if (!QApplicationPrivate::isBlockedByModal(host))
1445 QApplicationPrivate::enterModal(host);
1446 } else {
1447 if (QApplicationPrivate::isBlockedByModal(host))
1448 QApplicationPrivate::leaveModal(host);
1449 }
1450 qt_win_ignoreNextMouseReleaseEvent = false;
1451 return S_OK;
1452}
1453
1454HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, WORD grfModifiers)
1455{
1456 return TranslateAccelerator(lpMsg, (DWORD)grfModifiers);
1457}
1458
1459//**** IOleInPlaceUIWindow
1460HRESULT WINAPI QAxClientSite::GetBorder(LPRECT lprectBorder)
1461{
1462#ifndef QAX_SUPPORT_BORDERSPACE
1463 Q_UNUSED(lprectBorder);
1464 return INPLACE_E_NOTOOLSPACE;
1465#else
1466 AX_DEBUG(QAxClientSite::GetBorder);
1467
1468 QMainWindow *mw = qobject_cast<QMainWindow*>(widget->window());
1469 if (!mw)
1470 return INPLACE_E_NOTOOLSPACE;
1471
1472 RECT border = { 0,0, 300, 200 };
1473 *lprectBorder = border;
1474 return S_OK;
1475#endif
1476}
1477
1478HRESULT WINAPI QAxClientSite::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
1479{
1480#ifndef QAX_SUPPORT_BORDERSPACE
1481 return INPLACE_E_NOTOOLSPACE;
1482#else
1483 AX_DEBUG(QAxClientSite::RequestBorderSpace);
1484
1485 QMainWindow *mw = qobject_cast<QMainWindow*>(widget->window());
1486 if (!mw)
1487 return INPLACE_E_NOTOOLSPACE;
1488
1489 return S_OK;
1490#endif
1491}
1492
1493HRESULT WINAPI QAxClientSite::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
1494{
1495#ifndef QAX_SUPPORT_BORDERSPACE
1496 Q_UNUSED(pborderwidths);
1497 return OLE_E_INVALIDRECT;
1498#else
1499 AX_DEBUG(QAxClientSite::SetBorderSpace);
1500
1501 // object has no toolbars and wants container toolbars to remain
1502 if (!pborderwidths)
1503 return S_OK;
1504
1505 QMainWindow *mw = qobject_cast<QMainWindow*>(widget->window());
1506 if (!mw)
1507 return OLE_E_INVALIDRECT;
1508
1509 bool removeToolBars = !(pborderwidths->left || pborderwidths->top || pborderwidths->right || pborderwidths->bottom);
1510
1511 // object has toolbars, and wants container to remove toolbars
1512 if (removeToolBars) {
1513 if (mw) {
1514 //### remove our toolbars
1515 }
1516 }
1517
1518 if (pborderwidths->left) {
1519 QDockWidget *left = new QDockWidget(mw);
1520 left->setFixedWidth(pborderwidths->left);
1521 mw->addDockWidget(Qt::LeftDockWidgetArea, left);
1522 left->show();
1523 }
1524 if (pborderwidths->top) {
1525 QDockWidget *top = new QDockWidget(mw);
1526 top->setFixedHeight(pborderwidths->top);
1527 mw->addDockWidget(Qt::TopDockWidgetArea, top);
1528 top->show();
1529 }
1530
1531 return S_OK;
1532#endif
1533}
1534
1535HRESULT WINAPI QAxClientSite::SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
1536{
1537 AX_DEBUG(QAxClientSite::SetActiveObject);
1538
1539 Q_UNUSED(pszObjName);
1540 // we are ignoring the name of the object, as suggested by MSDN documentation
1541 // for IOleInPlaceUIWindow::SetActiveObject().
1542
1543 if (m_spInPlaceActiveObject) {
1544 if (!inPlaceModelessEnabled)
1545 m_spInPlaceActiveObject->EnableModeless(true);
1546 inPlaceModelessEnabled = true;
1547 m_spInPlaceActiveObject->Release();
1548 }
1549
1550 m_spInPlaceActiveObject = pActiveObject;
1551 if (m_spInPlaceActiveObject)
1552 m_spInPlaceActiveObject->AddRef();
1553
1554 return S_OK;
1555}
1556
1557//**** IOleDocumentSite
1558HRESULT WINAPI QAxClientSite::ActivateMe(IOleDocumentView *pViewToActivate)
1559{
1560 AX_DEBUG(QAxClientSite::ActivateMe);
1561
1562 if (m_spActiveView)
1563 m_spActiveView->Release();
1564 m_spActiveView = 0;
1565
1566 if (!pViewToActivate) {
1567 IOleDocument *document = 0;
1568 m_spOleObject->QueryInterface(IID_IOleDocument, (void**)&document);
1569 if (!document)
1570 return E_FAIL;
1571
1572 document->CreateView(this, 0, 0, &pViewToActivate);
1573
1574 document->Release();
1575 if (!pViewToActivate)
1576 return E_OUTOFMEMORY;
1577 } else {
1578 pViewToActivate->SetInPlaceSite(this);
1579 }
1580
1581 m_spActiveView = pViewToActivate;
1582 m_spActiveView->AddRef();
1583
1584 m_spActiveView->UIActivate(TRUE);
1585
1586 RECT rect;
1587 GetClientRect(widget->winId(), &rect);
1588 m_spActiveView->SetRect(&rect);
1589 m_spActiveView->Show(TRUE);
1590
1591 return S_OK;
1592}
1593
1594QSize QAxClientSite::minimumSizeHint() const
1595{
1596 if (!m_spOleObject)
1597 return QSize();
1598
1599 SIZE sz = { 0, 0 };
1600 m_spOleObject->SetExtent(DVASPECT_CONTENT, &sz);
1601 HRESULT res = m_spOleObject->GetExtent(DVASPECT_CONTENT, &sz);
1602 if (SUCCEEDED(res)) {
1603 return QSize(MAP_LOGHIM_TO_PIX(sz.cx, widget->logicalDpiX()),
1604 MAP_LOGHIM_TO_PIX(sz.cy, widget->logicalDpiY()));
1605 }
1606 return QSize();
1607}
1608
1609void QAxClientSite::windowActivationChange()
1610{
1611 AX_DEBUG(QAxClientSite::windowActivationChange);
1612
1613 if (m_spInPlaceActiveObject && widget) {
1614 QWidget *modal = QApplication::activeModalWidget();
1615 if (modal && inPlaceModelessEnabled) {
1616 m_spInPlaceActiveObject->EnableModeless(false);
1617 inPlaceModelessEnabled = false;
1618 } else if (!inPlaceModelessEnabled) {
1619 m_spInPlaceActiveObject->EnableModeless(true);
1620 inPlaceModelessEnabled = true;
1621 }
1622 m_spInPlaceActiveObject->OnFrameWindowActivate(widget->isActiveWindow());
1623 }
1624}
1625
1626
1627//**** QWidget
1628
1629QAxHostWidget::QAxHostWidget(QWidget *parent, QAxClientSite *ax)
1630: QWidget(parent), setFocusTimer(0), hasFocus(false), axhost(ax)
1631{
1632 setAttribute(Qt::WA_NoBackground);
1633 setAttribute(Qt::WA_NoSystemBackground);
1634 setAttribute(Qt::WA_OpaquePaintEvent);
1635 setAttribute(Qt::WA_PaintOnScreen);
1636
1637 setObjectName(parent->objectName() + QLatin1String(" - QAxHostWidget"));
1638}
1639
1640QAxHostWidget::~QAxHostWidget()
1641{
1642 if (axhost)
1643 axhost->reset(this);
1644}
1645
1646int QAxHostWidget::qt_metacall(QMetaObject::Call call, int isignal, void **argv)
1647{
1648 if (axhost)
1649 return axhost->qt_metacall(call, isignal, argv);
1650 return -1;
1651}
1652
1653void* QAxHostWidget::qt_metacast(const char *clname)
1654{
1655 if (!clname) return 0;
1656 if (!qstrcmp(clname,"QAxHostWidget"))
1657 return static_cast<void*>(const_cast< QAxHostWidget*>(this));
1658 return QWidget::qt_metacast(clname);
1659}
1660
1661QSize QAxHostWidget::sizeHint() const
1662{
1663 return axhost ? axhost->sizeHint() : QWidget::sizeHint();
1664}
1665
1666QSize QAxHostWidget::minimumSizeHint() const
1667{
1668 QSize size;
1669 if (axhost)
1670 size = axhost->minimumSizeHint();
1671 if (size.isValid())
1672 return size;
1673 return QWidget::minimumSizeHint();
1674}
1675
1676void QAxHostWidget::resizeObject()
1677{
1678 if (!axhost)
1679 return;
1680
1681 // document server - talk to view?
1682 if (axhost->m_spActiveView) {
1683 RECT rect;
1684 GetClientRect(winId(), &rect);
1685 axhost->m_spActiveView->SetRect(&rect);
1686
1687 return;
1688 }
1689
1690 SIZEL hmSize;
1691 hmSize.cx = MAP_PIX_TO_LOGHIM(width(), logicalDpiX());
1692 hmSize.cy = MAP_PIX_TO_LOGHIM(height(), logicalDpiY());
1693
1694 if (axhost->m_spOleObject)
1695 axhost->m_spOleObject->SetExtent(DVASPECT_CONTENT, &hmSize);
1696 if (axhost->m_spInPlaceObject) {
1697 RECT rcPos = { x(), y(), x()+width(), y()+height() };
1698 axhost->m_spInPlaceObject->SetObjectRects(&rcPos, &rcPos);
1699 }
1700}
1701
1702void QAxHostWidget::resizeEvent(QResizeEvent *)
1703{
1704 resizeObject();
1705}
1706
1707void QAxHostWidget::showEvent(QShowEvent *)
1708{
1709 resizeObject();
1710}
1711
1712bool QAxHostWidget::winEvent(MSG *msg, long *result)
1713{
1714 if (axhost && axhost->inPlaceObjectWindowless) {
1715 Q_ASSERT(axhost->m_spInPlaceObject);
1716 IOleInPlaceObjectWindowless *windowless = (IOleInPlaceObjectWindowless*)axhost->m_spInPlaceObject;
1717 Q_ASSERT(windowless);
1718 LRESULT lres;
1719 HRESULT hres = windowless->OnWindowMessage(msg->message, msg->wParam, msg->lParam, &lres);
1720 if (hres == S_OK)
1721 return true;
1722 }
1723 return QWidget::winEvent(msg, result);
1724}
1725
1726bool QAxHostWidget::event(QEvent *e)
1727{
1728 switch (e->type()) {
1729 case QEvent::Timer:
1730 if (axhost && ((QTimerEvent*)e)->timerId() == setFocusTimer) {
1731 killTimer(setFocusTimer);
1732 setFocusTimer = 0;
1733 RECT rcPos = { x(), y(), x()+size().width(), y()+size().height() };
1734 axhost->m_spOleObject->DoVerb(OLEIVERB_UIACTIVATE, 0, (IOleClientSite*)axhost, 0, winId(), &rcPos);
1735 if (axhost->m_spActiveView)
1736 axhost->m_spActiveView->UIActivate(TRUE);
1737 }
1738 break;
1739 case QEvent::WindowBlocked:
1740 if (IsWindowEnabled(winId())) {
1741 EnableWindow(winId(), false);
1742 if (axhost && axhost->m_spInPlaceActiveObject) {
1743 axhost->inPlaceModelessEnabled = false;
1744 axhost->m_spInPlaceActiveObject->EnableModeless(false);
1745 }
1746 }
1747 break;
1748 case QEvent::WindowUnblocked:
1749 if (!IsWindowEnabled(winId())) {
1750 EnableWindow(winId(), true);
1751 if (axhost && axhost->m_spInPlaceActiveObject) {
1752 axhost->inPlaceModelessEnabled = true;
1753 axhost->m_spInPlaceActiveObject->EnableModeless(true);
1754 }
1755 }
1756 break;
1757 default:
1758 break;
1759 }
1760
1761 return QWidget::event(e);
1762}
1763
1764bool QAxHostWidget::eventFilter(QObject *o, QEvent *e)
1765{
1766 // focus goes to Qt while ActiveX still has it - deactivate
1767 QWidget *newFocus = qobject_cast<QWidget*>(o);
1768 if (e->type() == QEvent::FocusIn && hasFocus
1769 && newFocus && newFocus->window() == window()) {
1770 if (axhost && axhost->m_spInPlaceActiveObject && axhost->m_spInPlaceObject)
1771 axhost->m_spInPlaceObject->UIDeactivate();
1772 qApp->removeEventFilter(this);
1773 }
1774
1775 return QWidget::eventFilter(o, e);
1776}
1777
1778void QAxHostWidget::focusInEvent(QFocusEvent *e)
1779{
1780 QWidget::focusInEvent(e);
1781
1782 if (!axhost || !axhost->m_spOleObject)
1783 return;
1784
1785 // this is called by QWidget::setFocus which calls ::SetFocus on "this",
1786 // so we have to UIActivate the control after all that had happend.
1787 AX_DEBUG(Setting focus on in-place object);
1788 setFocusTimer = startTimer(0);
1789}
1790
1791void QAxHostWidget::focusOutEvent(QFocusEvent *e)
1792{
1793 QWidget::focusOutEvent(e);
1794 if (setFocusTimer) {
1795 killTimer(setFocusTimer);
1796 setFocusTimer = 0;
1797 }
1798 if (e->reason() == Qt::PopupFocusReason || e->reason() == Qt::MenuBarFocusReason)
1799 return;
1800
1801 if (!axhost || !axhost->m_spInPlaceActiveObject || !axhost->m_spInPlaceObject)
1802 return;
1803
1804 AX_DEBUG(Deactivating in-place object);
1805 axhost->m_spInPlaceObject->UIDeactivate();
1806}
1807
1808
1809void QAxHostWidget::paintEvent(QPaintEvent*)
1810{
1811 if (!QPainter::redirected(this))
1812 return;
1813
1814 IViewObject *view = 0;
1815 if (axhost)
1816 axhost->widget->queryInterface(IID_IViewObject, (void**)&view);
1817 if (!view)
1818 return;
1819
1820 // somebody tries to grab us!
1821 QPixmap pm(size());
1822 pm.fill();
1823
1824 HBITMAP hBmp = pm.toWinHBITMAP();
1825 HDC hBmp_hdc = CreateCompatibleDC(qt_win_display_dc());
1826 HGDIOBJ old_hBmp = SelectObject(hBmp_hdc, hBmp);
1827
1828 RECTL bounds;
1829 bounds.left = 0;
1830 bounds.right = pm.width();
1831 bounds.top = 0;
1832 bounds.bottom = pm.height();
1833
1834 view->Draw(DVASPECT_CONTENT, -1, 0, 0, 0, hBmp_hdc, &bounds, 0, 0 /*fptr*/, 0);
1835 view->Release();
1836
1837 QPainter painter(this);
1838 painter.drawPixmap(0, 0, QPixmap::fromWinHBITMAP(hBmp));
1839
1840 SelectObject(hBmp_hdc, old_hBmp);
1841 DeleteObject(hBmp);
1842 DeleteDC(hBmp_hdc);
1843}
1844
1845/*!
1846 \class QAxWidget
1847 \brief The QAxWidget class is a QWidget that wraps an ActiveX control.
1848
1849 \inmodule QAxContainer
1850
1851 A QAxWidget can be instantiated as an empty object, with the name
1852 of the ActiveX control it should wrap, or with an existing
1853 interface pointer to the ActiveX control. The ActiveX control's
1854 properties, methods and events which only use QAxBase
1855 supported data types, become available as Qt properties,
1856 slots and signals. The base class QAxBase provides an API to
1857 access the ActiveX directly through the \c IUnknown pointer.
1858
1859 QAxWidget is a QWidget and can mostly be used as such, e.g. it can be
1860 organized in a widget hierarchy and layouts or act as an event filter.
1861 Standard widget properties, e.g. \link QWidget::enabled
1862 enabled \endlink are supported, but it depends on the ActiveX
1863 control to implement support for ambient properties like e.g.
1864 palette or font. QAxWidget tries to provide the necessary hints.
1865
1866 However, you cannot reimplement Qt-specific event handlers like
1867 mousePressEvent or keyPressEvent and expect them to be called reliably.
1868 The embedded control covers the QAxWidget completely, and usually
1869 handles the user interface itself. Use control-specific APIs (i.e. listen
1870 to the signals of the control), or use standard COM techniques like
1871 window procedure subclassing.
1872
1873 QAxWidget also inherits most of its ActiveX-related functionality
1874 from QAxBase, notably dynamicCall() and querySubObject().
1875
1876 \warning
1877 You can subclass QAxWidget, but you cannot use the \c Q_OBJECT macro
1878 in the subclass (the generated moc-file will not compile), so you
1879 cannot add further signals, slots or properties. This limitation
1880 is due to the metaobject information generated in runtime. To work
1881 around this problem, aggregate the QAxWidget as a member of the
1882 QObject subclass.
1883
1884 \sa QAxBase, QAxObject, QAxScript, {ActiveQt Framework}
1885*/
1886
1887/*!
1888 Creates an empty QAxWidget widget and propagates \a parent
1889 and \a f to the QWidget constructor. To initialize a control,
1890 call setControl().
1891*/
1892QAxWidget::QAxWidget(QWidget *parent, Qt::WindowFlags f)
1893: QWidget(parent, f), container(0)
1894{
1895}
1896
1897/*!
1898 Creates an QAxWidget widget and initializes the ActiveX control \a c.
1899 \a parent and \a f are propagated to the QWidget contructor.
1900
1901 \sa setControl()
1902*/
1903QAxWidget::QAxWidget(const QString &c, QWidget *parent, Qt::WindowFlags f)
1904: QWidget(parent, f), container(0)
1905{
1906 setControl(c);
1907}
1908
1909/*!
1910 Creates a QAxWidget that wraps the COM object referenced by \a iface.
1911 \a parent and \a f are propagated to the QWidget contructor.
1912*/
1913QAxWidget::QAxWidget(IUnknown *iface, QWidget *parent, Qt::WindowFlags f)
1914: QWidget(parent, f), QAxBase(iface), container(0)
1915{
1916}
1917
1918/*!
1919 Shuts down the ActiveX control and destroys the QAxWidget widget,
1920 cleaning up all allocated resources.
1921
1922 \sa clear()
1923*/
1924QAxWidget::~QAxWidget()
1925{
1926 if (container)
1927 container->reset(this);
1928 clear();
1929}
1930
1931/*!
1932 \since 4.2
1933
1934 Calls QAxBase::initialize(\a ptr), and embeds the control in this
1935 widget by calling createHostWindow(false) if successful.
1936
1937 To initialize the control before it is activated, reimplement this
1938 function and add your initialization code before you call
1939 createHostWindow(true).
1940*/
1941bool QAxWidget::initialize(IUnknown **ptr)
1942{
1943 if (!QAxBase::initialize(ptr))
1944 return false;
1945
1946 return createHostWindow(false); // assume that control is not initialized
1947}
1948
1949/*!
1950 Creates the client site for the ActiveX control, and returns true if
1951 the control could be embedded successfully, otherwise returns false.
1952 If \a initialized is true the control has already been initialized.
1953
1954 This function is called by initialize(). If you reimplement initialize
1955 to customize the actual control instantiation, call this function in your
1956 reimplementation to have the control embedded by the default client side.
1957 Creates the client site for the ActiveX control, and returns true if
1958 the control could be embedded successfully, otherwise returns false.
1959*/
1960bool QAxWidget::createHostWindow(bool initialized)
1961{
1962 return createHostWindow(initialized, QByteArray());
1963}
1964
1965/*!
1966 \since 4.4
1967
1968 Creates the client site for the ActiveX control, and returns true if
1969 the control could be embedded successfully, otherwise returns false.
1970 If \a initialized is false the control will be initialized using the
1971 \a data. The control will be initialized through either IPersistStreamInit
1972 or IPersistStorage interface.
1973
1974 If the control needs to be initialized using custom data, call this function
1975 in your reimplementation of initialize(). This function is not called by
1976 the default implementation of initialize().
1977*/
1978bool QAxWidget::createHostWindow(bool initialized, const QByteArray &data)
1979{
1980#ifdef QT3_SUPPORT
1981 QApplication::sendPostedEvents(0, QEvent::ChildInserted);
1982#endif
1983
1984 container = new QAxClientSite(this);
1985 container->activateObject(initialized, data);
1986
1987#if !defined(Q_OS_WINCE)
1988 ATOM filter_ref = FindAtom(qaxatom);
1989#endif
1990 if (!filter_ref)
1991 previous_filter = QAbstractEventDispatcher::instance()->setEventFilter(axc_FilterProc);
1992#if !defined(Q_OS_WINCE)
1993 AddAtom(qaxatom);
1994#else
1995 ++filter_ref;
1996#endif
1997
1998 if (parentWidget())
1999 QApplication::postEvent(parentWidget(), new QEvent(QEvent::LayoutRequest));
2000
2001 return true;
2002}
2003
2004/*!
2005 Reimplement this function when you want to implement additional
2006 COM interfaces for the client site of the ActiveX control, or when
2007 you want to provide alternative implementations of COM interfaces.
2008 Return a new object of a QAxAggregated subclass.
2009
2010 The default implementation returns the null pointer.
2011*/
2012QAxAggregated *QAxWidget::createAggregate()
2013{
2014 return 0;
2015}
2016
2017/*!
2018 \reimp
2019
2020 Shuts down the ActiveX control.
2021*/
2022void QAxWidget::clear()
2023{
2024 if (isNull())
2025 return;
2026 if (!control().isEmpty()) {
2027#if !defined(Q_OS_WINCE)
2028 ATOM filter_ref = FindAtom(qaxatom);
2029 if (filter_ref)
2030 DeleteAtom(filter_ref);
2031 filter_ref = FindAtom(qaxatom);
2032 if (!filter_ref) {
2033#else
2034 if (!filter_ref && !--filter_ref) {
2035#endif
2036 QAbstractEventDispatcher::instance()->setEventFilter(previous_filter);
2037 previous_filter = 0;
2038 }
2039 }
2040
2041 if (container)
2042 container->deactivate();
2043
2044 QAxBase::clear();
2045 setFocusPolicy(Qt::NoFocus);
2046
2047 if (container) {
2048 container->releaseAll();
2049 container->Release();
2050 }
2051 container = 0;
2052}
2053
2054/*!
2055 \since 4.1
2056
2057 Requests the ActiveX control to perform the action \a verb. The
2058 possible verbs are returned by verbs().
2059
2060 The function returns true if the object could perform the action, otherwise returns false.
2061*/
2062bool QAxWidget::doVerb(const QString &verb)
2063{
2064 if (!verbs().contains(verb))
2065 return false;
2066
2067 HRESULT hres = container->doVerb(indexOfVerb(verb));
2068
2069 return hres == S_OK;
2070}
2071
2072 /*!
2073 \fn QObject *QAxWidget::qObject() const
2074 \internal
2075*/
2076
2077/*!
2078 \internal
2079*/
2080const QMetaObject *QAxWidget::metaObject() const
2081{
2082 return QAxBase::metaObject();
2083}
2084
2085/*!
2086 \internal
2087*/
2088const QMetaObject *QAxWidget::parentMetaObject() const
2089{
2090 return &QWidget::staticMetaObject;
2091}
2092
2093/*!
2094 \internal
2095*/
2096void *QAxWidget::qt_metacast(const char *cname)
2097{
2098 if (!qstrcmp(cname, "QAxWidget")) return (void*)this;
2099 if (!qstrcmp(cname, "QAxBase")) return (QAxBase*)this;
2100 return QWidget::qt_metacast(cname);
2101}
2102
2103/*!
2104 \internal
2105*/
2106const char *QAxWidget::className() const
2107{
2108 return "QAxWidget";
2109}
2110
2111/*!
2112 \internal
2113*/
2114int QAxWidget::qt_metacall(QMetaObject::Call call, int id, void **v)
2115{
2116 id = QWidget::qt_metacall(call, id, v);
2117 if (id < 0)
2118 return id;
2119 return QAxBase::qt_metacall(call, id, v);
2120}
2121
2122/*!
2123 \reimp
2124*/
2125QSize QAxWidget::sizeHint() const
2126{
2127 if (container) {
2128 QSize sh = container->sizeHint();
2129 if (sh.isValid())
2130 return sh;
2131 }
2132
2133 return QWidget::sizeHint();
2134}
2135
2136/*!
2137 \reimp
2138*/
2139QSize QAxWidget::minimumSizeHint() const
2140{
2141 if (container) {
2142 QSize sh = container->minimumSizeHint();
2143 if (sh.isValid())
2144 return sh;
2145 }
2146
2147 return QWidget::minimumSizeHint();
2148}
2149
2150/*!
2151 \reimp
2152*/
2153void QAxWidget::changeEvent(QEvent *e)
2154{
2155 if (isNull())
2156 return;
2157
2158 switch (e->type()) {
2159 case QEvent::EnabledChange:
2160 container->emitAmbientPropertyChange(DISPID_AMBIENT_UIDEAD);
2161 break;
2162 case QEvent::FontChange:
2163 container->emitAmbientPropertyChange(DISPID_AMBIENT_FONT);
2164 break;
2165 case QEvent::PaletteChange:
2166 container->emitAmbientPropertyChange(DISPID_AMBIENT_BACKCOLOR);
2167 container->emitAmbientPropertyChange(DISPID_AMBIENT_FORECOLOR);
2168 break;
2169 case QEvent::ActivationChange:
2170 container->windowActivationChange();
2171 break;
2172 default:
2173 break;
2174 }
2175}
2176
2177/*!
2178 \reimp
2179*/
2180void QAxWidget::resizeEvent(QResizeEvent *)
2181{
2182 if (container)
2183 container->resize(size());
2184}
2185
2186/*!
2187 \reimp
2188*/
2189void QAxWidget::connectNotify(const char *)
2190{
2191 QAxBase::connectNotify();
2192}
2193
2194
2195/*!
2196 Reimplement this function to pass certain key events to the
2197 ActiveX control. \a message is the Window message identifier
2198 specifying the message type (ie. WM_KEYDOWN), and \a keycode is
2199 the virtual keycode (ie. VK_TAB).
2200
2201 If the function returns true the key event is passed on to the
2202 ActiveX control, which then either processes the event or passes
2203 the event on to Qt.
2204
2205 If the function returns false the processing of the key event is
2206 ignored by ActiveQt, ie. the ActiveX control might handle it or
2207 not.
2208
2209 The default implementation returns true for the following cases:
2210
2211 \table
2212 \header
2213 \i WM_SYSKEYDOWN
2214 \i WM_SYSKEYUP
2215 \i WM_KEYDOWN
2216 \row
2217 \i All keycodes
2218 \i VK_MENU
2219 \i VK_TAB, VK_DELETE and all non-arrow-keys in combination with VK_SHIFT,
2220 VK_CONTROL or VK_MENU
2221 \endtable
2222
2223 This table is the result of experimenting with popular ActiveX controls,
2224 ie. Internet Explorer and Microsoft Office applications, but for some
2225 controls it might require modification.
2226*/
2227bool QAxWidget::translateKeyEvent(int message, int keycode) const
2228{
2229 bool translate = false;
2230
2231 switch (message) {
2232 case WM_SYSKEYDOWN:
2233 translate = true;
2234 break;
2235 case WM_KEYDOWN:
2236 translate = keycode == VK_TAB
2237 || keycode == VK_DELETE;
2238 if (!translate) {
2239 int state = 0;
2240 if (GetKeyState(VK_SHIFT) < 0)
2241 state |= 0x01;
2242 if (GetKeyState(VK_CONTROL) < 0)
2243 state |= 0x02;
2244 if (GetKeyState(VK_MENU) < 0)
2245 state |= 0x04;
2246 if (state) {
2247 state = keycode < VK_LEFT || keycode > VK_DOWN;
2248 }
2249 translate = state;
2250 }
2251 break;
2252 case WM_SYSKEYUP:
2253 translate = keycode == VK_MENU;
2254 break;
2255 }
2256
2257 return translate;
2258}
2259
2260QT_END_NAMESPACE
2261#endif // QT_NO_WIN_ACTIVEQT
Note: See TracBrowser for help on using the repository browser.