0
|
1 |
/****************************************************************************
|
|
2 |
**
|
|
3 |
** Copyright (C) 2009 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 |
|
|
103 |
QT_BEGIN_NAMESPACE
|
|
104 |
|
|
105 |
/* \class QAxHostWidget
|
|
106 |
\brief The QAxHostWidget class is the actual container widget.
|
|
107 |
|
|
108 |
\internal
|
|
109 |
*/
|
|
110 |
class QAxHostWidget : public QWidget
|
|
111 |
{
|
|
112 |
friend class QAxClientSite;
|
|
113 |
public:
|
|
114 |
Q_OBJECT_CHECK
|
|
115 |
QAxHostWidget(QWidget *parent, QAxClientSite *ax);
|
|
116 |
~QAxHostWidget();
|
|
117 |
|
|
118 |
QSize sizeHint() const;
|
|
119 |
QSize minimumSizeHint() const;
|
|
120 |
|
|
121 |
int qt_metacall(QMetaObject::Call, int isignal, void **argv);
|
|
122 |
void* qt_metacast(const char *clname);
|
|
123 |
|
|
124 |
inline QAxClientSite *clientSite() const
|
|
125 |
{
|
|
126 |
return axhost;
|
|
127 |
}
|
|
128 |
|
|
129 |
protected:
|
|
130 |
bool winEvent(MSG *msg, long *result);
|
|
131 |
bool event(QEvent *e);
|
|
132 |
bool eventFilter(QObject *o, QEvent *e);
|
|
133 |
void resizeEvent(QResizeEvent *e);
|
|
134 |
void focusInEvent(QFocusEvent *e);
|
|
135 |
void focusOutEvent(QFocusEvent *e);
|
|
136 |
void paintEvent(QPaintEvent *e);
|
|
137 |
void showEvent(QShowEvent *e);
|
|
138 |
QPaintEngine* paintEngine() const
|
|
139 |
{
|
|
140 |
return 0;
|
|
141 |
}
|
|
142 |
|
|
143 |
private:
|
|
144 |
void resizeObject();
|
|
145 |
|
|
146 |
int setFocusTimer;
|
|
147 |
bool hasFocus;
|
|
148 |
QAxClientSite *axhost;
|
|
149 |
};
|
|
150 |
|
|
151 |
/* \class QAxClientSite
|
|
152 |
\brief The QAxClientSite class implements the client site interfaces.
|
|
153 |
|
|
154 |
\internal
|
|
155 |
*/
|
|
156 |
class QAxClientSite : public IDispatch,
|
|
157 |
public IOleClientSite,
|
|
158 |
public IOleControlSite,
|
|
159 |
#ifdef QAX_SUPPORT_WINDOWLESS
|
|
160 |
public IOleInPlaceSiteWindowless,
|
|
161 |
#else
|
|
162 |
public IOleInPlaceSite,
|
|
163 |
#endif
|
|
164 |
public IOleInPlaceFrame,
|
|
165 |
public IOleDocumentSite,
|
|
166 |
public IAdviseSink
|
|
167 |
{
|
|
168 |
friend class QAxHostWidget;
|
|
169 |
public:
|
|
170 |
QAxClientSite(QAxWidget *c);
|
|
171 |
virtual ~QAxClientSite();
|
|
172 |
|
|
173 |
bool activateObject(bool initialized, const QByteArray &data);
|
|
174 |
|
|
175 |
void releaseAll();
|
|
176 |
void deactivate();
|
|
177 |
inline void reset(QWidget *p)
|
|
178 |
{
|
|
179 |
if (widget == p)
|
|
180 |
widget = 0;
|
|
181 |
else if (host == p)
|
|
182 |
host = 0;
|
|
183 |
}
|
|
184 |
|
|
185 |
inline IOleInPlaceActiveObject *inPlaceObject() const
|
|
186 |
{
|
|
187 |
return m_spInPlaceActiveObject;
|
|
188 |
}
|
|
189 |
|
|
190 |
inline HRESULT doVerb(LONG index)
|
|
191 |
{
|
|
192 |
if (!m_spOleObject)
|
|
193 |
return E_NOTIMPL;
|
|
194 |
if (!host)
|
|
195 |
return OLE_E_NOT_INPLACEACTIVE;
|
|
196 |
|
|
197 |
RECT rcPos = { host->x(), host->y(), host->x()+host->width(), host->y()+host->height() };
|
|
198 |
return m_spOleObject->DoVerb(index, 0, this, 0, host->winId(), &rcPos);
|
|
199 |
}
|
|
200 |
|
|
201 |
// IUnknown
|
|
202 |
unsigned long WINAPI AddRef();
|
|
203 |
unsigned long WINAPI Release();
|
|
204 |
STDMETHOD(QueryInterface)(REFIID iid, void **iface);
|
|
205 |
|
|
206 |
// IDispatch
|
|
207 |
HRESULT __stdcall GetTypeInfoCount(unsigned int *) { return E_NOTIMPL; }
|
|
208 |
HRESULT __stdcall GetTypeInfo(UINT, LCID, ITypeInfo **) { return E_NOTIMPL; }
|
|
209 |
HRESULT __stdcall GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *) { return E_NOTIMPL; }
|
|
210 |
HRESULT __stdcall Invoke(DISPID dispIdMember,
|
|
211 |
REFIID riid,
|
|
212 |
LCID lcid,
|
|
213 |
WORD wFlags,
|
|
214 |
DISPPARAMS *pDispParams,
|
|
215 |
VARIANT *pVarResult,
|
|
216 |
EXCEPINFO *pExcepInfo,
|
|
217 |
UINT *puArgErr);
|
|
218 |
void emitAmbientPropertyChange(DISPID dispid);
|
|
219 |
|
|
220 |
// IOleClientSite
|
|
221 |
STDMETHOD(SaveObject)();
|
|
222 |
STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk);
|
|
223 |
STDMETHOD(GetContainer)(LPOLECONTAINER FAR* ppContainer);
|
|
224 |
STDMETHOD(ShowObject)();
|
|
225 |
STDMETHOD(OnShowWindow)(BOOL fShow);
|
|
226 |
STDMETHOD(RequestNewObjectLayout)();
|
|
227 |
|
|
228 |
// IOleControlSite
|
|
229 |
STDMETHOD(OnControlInfoChanged)();
|
|
230 |
STDMETHOD(LockInPlaceActive)(BOOL fLock);
|
|
231 |
STDMETHOD(GetExtendedControl)(IDispatch** ppDisp);
|
|
232 |
STDMETHOD(TransformCoords)(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags);
|
|
233 |
STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, DWORD grfModifiers);
|
|
234 |
STDMETHOD(OnFocus)(BOOL fGotFocus);
|
|
235 |
STDMETHOD(ShowPropertyFrame)();
|
|
236 |
|
|
237 |
// IOleWindow
|
|
238 |
STDMETHOD(GetWindow)(HWND *phwnd);
|
|
239 |
STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode);
|
|
240 |
|
|
241 |
// IOleInPlaceSite
|
|
242 |
STDMETHOD(CanInPlaceActivate)();
|
|
243 |
STDMETHOD(OnInPlaceActivate)();
|
|
244 |
STDMETHOD(OnUIActivate)();
|
|
245 |
STDMETHOD(GetWindowContext)(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo);
|
|
246 |
STDMETHOD(Scroll)(SIZE scrollExtant);
|
|
247 |
STDMETHOD(OnUIDeactivate)(BOOL fUndoable);
|
|
248 |
STDMETHOD(OnInPlaceDeactivate)();
|
|
249 |
STDMETHOD(DiscardUndoState)();
|
|
250 |
STDMETHOD(DeactivateAndUndo)();
|
|
251 |
STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect);
|
|
252 |
|
|
253 |
#ifdef QAX_SUPPORT_WINDOWLESS
|
|
254 |
// IOleInPlaceSiteEx ###
|
|
255 |
STDMETHOD(OnInPlaceActivateEx)(BOOL* /*pfNoRedraw*/, DWORD /*dwFlags*/)
|
|
256 |
{
|
|
257 |
return S_OK;
|
|
258 |
}
|
|
259 |
STDMETHOD(OnInPlaceDeactivateEx)(BOOL /*fNoRedraw*/)
|
|
260 |
{
|
|
261 |
return S_OK;
|
|
262 |
}
|
|
263 |
STDMETHOD(RequestUIActivate)()
|
|
264 |
{
|
|
265 |
return S_OK;
|
|
266 |
}
|
|
267 |
|
|
268 |
// IOleInPlaceSiteWindowless ###
|
|
269 |
STDMETHOD(CanWindowlessActivate)()
|
|
270 |
{
|
|
271 |
return S_OK;
|
|
272 |
}
|
|
273 |
STDMETHOD(GetCapture)()
|
|
274 |
{
|
|
275 |
return S_FALSE;
|
|
276 |
}
|
|
277 |
STDMETHOD(SetCapture)(BOOL /*fCapture*/)
|
|
278 |
{
|
|
279 |
return S_FALSE;
|
|
280 |
}
|
|
281 |
STDMETHOD(GetFocus)()
|
|
282 |
{
|
|
283 |
return S_FALSE;
|
|
284 |
}
|
|
285 |
STDMETHOD(SetFocus)(BOOL /*fCapture*/)
|
|
286 |
{
|
|
287 |
return S_FALSE;
|
|
288 |
}
|
|
289 |
STDMETHOD(GetDC)(LPCRECT /*pRect*/, DWORD /*grfFlags*/, HDC *phDC)
|
|
290 |
{
|
|
291 |
*phDC = 0;
|
|
292 |
return S_OK;
|
|
293 |
}
|
|
294 |
STDMETHOD(ReleaseDC)(HDC hDC)
|
|
295 |
{
|
|
296 |
::ReleaseDC(widget->winId(), hDC);
|
|
297 |
return S_OK;
|
|
298 |
}
|
|
299 |
STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase)
|
|
300 |
{
|
|
301 |
::InvalidateRect(host->winId(), pRect, fErase);
|
|
302 |
return S_OK;
|
|
303 |
}
|
|
304 |
STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase)
|
|
305 |
{
|
|
306 |
::InvalidateRgn(host->winId(), hRGN, fErase);
|
|
307 |
return S_OK;
|
|
308 |
}
|
|
309 |
STDMETHOD(ScrollRect)(int /*dx*/, int /*dy*/, LPCRECT /*pRectScroll*/, LPCRECT /*pRectClip*/)
|
|
310 |
{
|
|
311 |
return S_OK;
|
|
312 |
}
|
|
313 |
STDMETHOD(AdjustRect)(LPRECT /*prc*/)
|
|
314 |
{
|
|
315 |
return S_OK;
|
|
316 |
}
|
|
317 |
#ifdef Q_CC_GNU // signature incorrect in win32api
|
|
318 |
STDMETHOD(AdjustRect)(LPCRECT /*prc*/)
|
|
319 |
{
|
|
320 |
RECT rect;
|
|
321 |
return AdjustRect(&rect);
|
|
322 |
}
|
|
323 |
#endif
|
|
324 |
|
|
325 |
STDMETHOD(OnDefWindowMessage)(UINT /*msg*/, WPARAM /*wPara*/, LPARAM /*lParam*/, LRESULT* /*plResult*/)
|
|
326 |
{
|
|
327 |
return S_FALSE;
|
|
328 |
}
|
|
329 |
#endif
|
|
330 |
|
|
331 |
// IOleInPlaceFrame
|
|
332 |
STDMETHOD(InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths));
|
|
333 |
STDMETHOD(SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject));
|
|
334 |
STDMETHOD(RemoveMenus(HMENU hmenuShared));
|
|
335 |
STDMETHOD(SetStatusText(LPCOLESTR pszStatusText));
|
|
336 |
STDMETHOD(EnableModeless(BOOL fEnable));
|
|
337 |
STDMETHOD(TranslateAccelerator(LPMSG lpMsg, WORD grfModifiers));
|
|
338 |
|
|
339 |
// IOleInPlaceUIWindow
|
|
340 |
STDMETHOD(GetBorder(LPRECT lprectBorder));
|
|
341 |
STDMETHOD(RequestBorderSpace(LPCBORDERWIDTHS pborderwidths));
|
|
342 |
STDMETHOD(SetBorderSpace(LPCBORDERWIDTHS pborderwidths));
|
|
343 |
STDMETHOD(SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName));
|
|
344 |
|
|
345 |
// IOleDocumentSite
|
|
346 |
STDMETHOD(ActivateMe(IOleDocumentView *pViewToActivate));
|
|
347 |
|
|
348 |
// IAdviseSink
|
|
349 |
STDMETHOD_(void, OnDataChange)(FORMATETC* /*pFormatetc*/, STGMEDIUM* /*pStgmed*/)
|
|
350 |
{
|
|
351 |
AX_DEBUG(QAxClientSite::OnDataChange);
|
|
352 |
}
|
|
353 |
STDMETHOD_(void, OnViewChange)(DWORD /*dwAspect*/, LONG /*lindex*/)
|
|
354 |
{
|
|
355 |
AX_DEBUG(QAxClientSite::OnViewChange);
|
|
356 |
}
|
|
357 |
STDMETHOD_(void, OnRename)(IMoniker* /*pmk*/)
|
|
358 |
{
|
|
359 |
}
|
|
360 |
STDMETHOD_(void, OnSave)()
|
|
361 |
{
|
|
362 |
}
|
|
363 |
STDMETHOD_(void, OnClose)()
|
|
364 |
{
|
|
365 |
}
|
|
366 |
|
|
367 |
QSize sizeHint() const { return sizehint; }
|
|
368 |
QSize minimumSizeHint() const;
|
|
369 |
inline void resize(QSize sz) { if (host) host->resize(sz); }
|
|
370 |
|
|
371 |
bool translateKeyEvent(int message, int keycode) const
|
|
372 |
{
|
|
373 |
if (!widget)
|
|
374 |
return false;
|
|
375 |
return widget->translateKeyEvent(message, keycode);
|
|
376 |
}
|
|
377 |
|
|
378 |
int qt_metacall(QMetaObject::Call, int isignal, void **argv);
|
|
379 |
void windowActivationChange();
|
|
380 |
|
|
381 |
bool eventTranslated : 1;
|
|
382 |
|
|
383 |
private:
|
|
384 |
#if !defined(Q_WS_WINCE)
|
|
385 |
struct OleMenuItem {
|
|
386 |
OleMenuItem(HMENU hm = 0, int ID = 0, QMenu *menu = 0)
|
|
387 |
: hMenu(hm), id(ID), subMenu(menu)
|
|
388 |
{}
|
|
389 |
HMENU hMenu;
|
|
390 |
int id;
|
|
391 |
QMenu *subMenu;
|
|
392 |
};
|
|
393 |
QMenu *generatePopup(HMENU subMenu, QWidget *parent);
|
|
394 |
#endif
|
|
395 |
|
|
396 |
IOleObject *m_spOleObject;
|
|
397 |
IOleControl *m_spOleControl;
|
|
398 |
IOleInPlaceObjectWindowless *m_spInPlaceObject;
|
|
399 |
IOleInPlaceActiveObject *m_spInPlaceActiveObject;
|
|
400 |
IOleDocumentView *m_spActiveView;
|
|
401 |
|
|
402 |
QAxAggregated *aggregatedObject;
|
|
403 |
|
|
404 |
bool inPlaceObjectWindowless :1;
|
|
405 |
bool inPlaceModelessEnabled :1;
|
|
406 |
bool canHostDocument : 1;
|
|
407 |
|
|
408 |
DWORD m_dwOleObject;
|
|
409 |
#if !defined(Q_WS_WINCE)
|
|
410 |
HWND m_menuOwner;
|
|
411 |
#endif
|
|
412 |
CONTROLINFO control_info;
|
|
413 |
|
|
414 |
QSize sizehint;
|
|
415 |
unsigned long ref;
|
|
416 |
QAxWidget *widget;
|
|
417 |
QAxHostWidget *host;
|
|
418 |
#if !defined(Q_WS_WINCE)
|
|
419 |
QPointer<QMenuBar> menuBar;
|
|
420 |
QMap<QAction*,OleMenuItem> menuItemMap;
|
|
421 |
#endif
|
|
422 |
};
|
|
423 |
|
|
424 |
static const ushort mouseTbl[] = {
|
|
425 |
WM_MOUSEMOVE, QEvent::MouseMove, 0,
|
|
426 |
WM_LBUTTONDOWN, QEvent::MouseButtonPress, Qt::LeftButton,
|
|
427 |
WM_LBUTTONUP, QEvent::MouseButtonRelease, Qt::LeftButton,
|
|
428 |
WM_LBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::LeftButton,
|
|
429 |
WM_RBUTTONDOWN, QEvent::MouseButtonPress, Qt::RightButton,
|
|
430 |
WM_RBUTTONUP, QEvent::MouseButtonRelease, Qt::RightButton,
|
|
431 |
WM_RBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::RightButton,
|
|
432 |
WM_MBUTTONDOWN, QEvent::MouseButtonPress, Qt::MidButton,
|
|
433 |
WM_MBUTTONUP, QEvent::MouseButtonRelease, Qt::MidButton,
|
|
434 |
WM_MBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::MidButton,
|
|
435 |
0, 0, 0
|
|
436 |
};
|
|
437 |
|
|
438 |
static Qt::MouseButtons translateMouseButtonState(int s)
|
|
439 |
{
|
|
440 |
Qt::MouseButtons bst = 0;
|
|
441 |
if (s & MK_LBUTTON)
|
|
442 |
bst |= Qt::LeftButton;
|
|
443 |
if (s & MK_MBUTTON)
|
|
444 |
bst |= Qt::MidButton;
|
|
445 |
if (s & MK_RBUTTON)
|
|
446 |
bst |= Qt::RightButton;
|
|
447 |
|
|
448 |
return bst;
|
|
449 |
}
|
|
450 |
|
|
451 |
static Qt::KeyboardModifiers translateModifierState(int s)
|
|
452 |
{
|
|
453 |
Qt::KeyboardModifiers bst = 0;
|
|
454 |
if (s & MK_SHIFT)
|
|
455 |
bst |= Qt::ShiftModifier;
|
|
456 |
if (s & MK_CONTROL)
|
|
457 |
bst |= Qt::ControlModifier;
|
|
458 |
if (GetKeyState(VK_MENU) < 0)
|
|
459 |
bst |= Qt::AltModifier;
|
|
460 |
|
|
461 |
return bst;
|
|
462 |
}
|
|
463 |
|
|
464 |
static QAbstractEventDispatcher::EventFilter previous_filter = 0;
|
|
465 |
#if QT_VERSION >= 0x050000
|
|
466 |
#error "Fix QAbstractEventDispatcher::setEventFilter"
|
|
467 |
#endif
|
|
468 |
#if defined(Q_WS_WINCE)
|
|
469 |
static int filter_ref = 0;
|
|
470 |
#else
|
|
471 |
static const wchar_t *qaxatom = L"QAxContainer4_Atom";
|
|
472 |
#endif
|
|
473 |
|
|
474 |
// The filter procedure listening to user interaction on the control
|
|
475 |
bool axc_FilterProc(void *m)
|
|
476 |
{
|
|
477 |
MSG *msg = (MSG*)m;
|
|
478 |
const uint message = msg->message;
|
|
479 |
if ((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) || (message >= WM_KEYFIRST && message <= WM_KEYLAST)) {
|
|
480 |
HWND hwnd = msg->hwnd;
|
|
481 |
QAxWidget *ax = 0;
|
|
482 |
QAxHostWidget *host = 0;
|
|
483 |
while (!host && hwnd) {
|
|
484 |
QWidget *widget = QWidget::find(hwnd);
|
|
485 |
if (widget && widget->inherits("QAxHostWidget"))
|
|
486 |
host = qobject_cast<QAxHostWidget*>(widget);
|
|
487 |
hwnd = ::GetParent(hwnd);
|
|
488 |
}
|
|
489 |
if (host)
|
|
490 |
ax = qobject_cast<QAxWidget*>(host->parentWidget());
|
|
491 |
if (ax && msg->hwnd != host->winId()) {
|
|
492 |
if (message >= WM_KEYFIRST && message <= WM_KEYLAST) {
|
|
493 |
QAxClientSite *site = host->clientSite();
|
|
494 |
site->eventTranslated = true; // reset in QAxClientSite::TranslateAccelerator
|
|
495 |
HRESULT hres = S_FALSE;
|
|
496 |
if (site && site->inPlaceObject() && site->translateKeyEvent(msg->message, msg->wParam))
|
|
497 |
hres = site->inPlaceObject()->TranslateAccelerator(msg);
|
|
498 |
// if the object calls our TranslateAccelerator implementation, then continue with normal event processing
|
|
499 |
// otherwise the object has translated the accelerator, and the event should be stopped
|
|
500 |
if (site->eventTranslated && hres == S_OK)
|
|
501 |
return true;
|
|
502 |
} else {
|
|
503 |
int i;
|
|
504 |
for (i = 0; (UINT)mouseTbl[i] != message && mouseTbl[i]; i += 3)
|
|
505 |
;
|
|
506 |
|
|
507 |
if (mouseTbl[i]) {
|
|
508 |
QEvent::Type type = (QEvent::Type)mouseTbl[++i];
|
|
509 |
int button = mouseTbl[++i];
|
|
510 |
if (type != QEvent::MouseMove || ax->hasMouseTracking() || button) {
|
|
511 |
if (type == QEvent::MouseMove)
|
|
512 |
button = 0;
|
|
513 |
|
|
514 |
DWORD ol_pos = GetMessagePos();
|
|
515 |
QPoint gpos(GET_X_LPARAM(ol_pos), GET_Y_LPARAM(ol_pos));
|
|
516 |
QPoint pos = ax->mapFromGlobal(gpos);
|
|
517 |
|
|
518 |
QMouseEvent e(type, pos, gpos, (Qt::MouseButton)button,
|
|
519 |
translateMouseButtonState(msg->wParam),
|
|
520 |
translateModifierState(msg->wParam));
|
|
521 |
QApplication::sendEvent(ax, &e);
|
|
522 |
}
|
|
523 |
}
|
|
524 |
}
|
|
525 |
}
|
|
526 |
}
|
|
527 |
|
|
528 |
if (previous_filter)
|
|
529 |
return previous_filter(m);
|
|
530 |
|
|
531 |
return false;
|
|
532 |
}
|
|
533 |
|
|
534 |
QAxClientSite::QAxClientSite(QAxWidget *c)
|
|
535 |
: eventTranslated(true), ref(1), widget(c), host(0)
|
|
536 |
{
|
|
537 |
aggregatedObject = widget->createAggregate();
|
|
538 |
if (aggregatedObject) {
|
|
539 |
aggregatedObject->controlling_unknown = (IUnknown*)(IDispatch*)this;
|
|
540 |
aggregatedObject->the_object = c;
|
|
541 |
}
|
|
542 |
|
|
543 |
m_spOleObject = 0;
|
|
544 |
m_spOleControl = 0;
|
|
545 |
m_spInPlaceObject = 0;
|
|
546 |
m_spInPlaceActiveObject = 0;
|
|
547 |
m_spActiveView = 0;
|
|
548 |
|
|
549 |
inPlaceObjectWindowless = false;
|
|
550 |
inPlaceModelessEnabled = true;
|
|
551 |
canHostDocument = false;
|
|
552 |
|
|
553 |
m_dwOleObject = 0;
|
|
554 |
#if !defined(Q_WS_WINCE)
|
|
555 |
m_menuOwner = 0;
|
|
556 |
menuBar = 0;
|
|
557 |
#endif
|
|
558 |
memset(&control_info, 0, sizeof(control_info));
|
|
559 |
}
|
|
560 |
|
|
561 |
bool QAxClientSite::activateObject(bool initialized, const QByteArray &data)
|
|
562 |
{
|
|
563 |
if (!host)
|
|
564 |
host = new QAxHostWidget(widget, this);
|
|
565 |
|
|
566 |
bool showHost = false;
|
|
567 |
HRESULT hr = S_OK;
|
|
568 |
if (!m_spOleObject)
|
|
569 |
widget->queryInterface(IID_IOleObject, (void**)&m_spOleObject);
|
|
570 |
if (m_spOleObject) {
|
|
571 |
DWORD dwMiscStatus = 0;
|
|
572 |
m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
|
|
573 |
|
|
574 |
#if !defined(Q_OS_WINCE)
|
|
575 |
IOleDocument *document = 0;
|
|
576 |
m_spOleObject->QueryInterface(IID_IOleDocument, (void**)&document);
|
|
577 |
if (document) {
|
|
578 |
IPersistStorage *persistStorage = 0;
|
|
579 |
document->QueryInterface(IID_IPersistStorage, (void**)&persistStorage);
|
|
580 |
if (persistStorage) {
|
|
581 |
// try to activate as document server
|
|
582 |
IStorage *storage = 0;
|
|
583 |
ILockBytes * bytes = 0;
|
|
584 |
HRESULT hres = ::CreateILockBytesOnHGlobal(0, TRUE, &bytes);
|
|
585 |
hres = ::StgCreateDocfileOnILockBytes(bytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &storage);
|
|
586 |
|
|
587 |
persistStorage->InitNew(storage);
|
|
588 |
persistStorage->Release();
|
|
589 |
canHostDocument = true;
|
|
590 |
storage->Release();
|
|
591 |
bytes->Release();
|
|
592 |
|
|
593 |
m_spOleObject->SetClientSite(this);
|
|
594 |
OleRun(m_spOleObject);
|
|
595 |
}
|
|
596 |
document->Release();
|
|
597 |
}
|
|
598 |
#endif
|
|
599 |
|
|
600 |
if (!canHostDocument) {
|
|
601 |
// activate as control
|
|
602 |
if(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
|
|
603 |
m_spOleObject->SetClientSite(this);
|
|
604 |
|
|
605 |
if (!initialized) {
|
|
606 |
IPersistStreamInit *spPSI = 0;
|
|
607 |
m_spOleObject->QueryInterface(IID_IPersistStreamInit, (void**)&spPSI);
|
|
608 |
if (spPSI) {
|
|
609 |
if (data.length()) {
|
|
610 |
IStream *pStream = 0;
|
|
611 |
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, data.length());
|
|
612 |
if (hGlobal) {
|
|
613 |
BYTE *pStByte = (BYTE *)GlobalLock(hGlobal);
|
|
614 |
if (pStByte)
|
|
615 |
memcpy(pStByte, data.data(), data.length());
|
|
616 |
GlobalUnlock(hGlobal);
|
|
617 |
if (SUCCEEDED(CreateStreamOnHGlobal(hGlobal, TRUE, &pStream))) {
|
|
618 |
spPSI->Load(pStream);
|
|
619 |
pStream->Release();
|
|
620 |
}
|
|
621 |
GlobalFree(hGlobal);
|
|
622 |
}
|
|
623 |
} else {
|
|
624 |
spPSI->InitNew();
|
|
625 |
}
|
|
626 |
spPSI->Release();
|
|
627 |
} else if (data.length()) { //try initializing using a IPersistStorage
|
|
628 |
IPersistStorage *spPS = 0;
|
|
629 |
m_spOleObject->QueryInterface( IID_IPersistStorage, (void**)&spPS );
|
|
630 |
if (spPS) {
|
|
631 |
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, data.length());
|
|
632 |
if (hGlobal) {
|
|
633 |
#if !defined(Q_OS_WINCE)
|
|
634 |
BYTE* pbData = (BYTE*)GlobalLock(hGlobal);
|
|
635 |
if (pbData)
|
|
636 |
memcpy(pbData, data.data(), data.length());
|
|
637 |
GlobalUnlock(hGlobal);
|
|
638 |
// open an IStorage on the data and pass it to Load
|
|
639 |
LPLOCKBYTES pLockBytes = 0;
|
|
640 |
if (SUCCEEDED(CreateILockBytesOnHGlobal(hGlobal, TRUE, &pLockBytes))) {
|
|
641 |
LPSTORAGE pStorage = 0;
|
|
642 |
if (SUCCEEDED(StgOpenStorageOnILockBytes(pLockBytes, 0,
|
|
643 |
STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStorage))) {
|
|
644 |
spPS->Load(pStorage);
|
|
645 |
pStorage->Release();
|
|
646 |
}
|
|
647 |
pLockBytes->Release();
|
|
648 |
}
|
|
649 |
GlobalFree(hGlobal);
|
|
650 |
#endif
|
|
651 |
}
|
|
652 |
spPS->Release();
|
|
653 |
}
|
|
654 |
}
|
|
655 |
}
|
|
656 |
|
|
657 |
if(!(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
|
|
658 |
m_spOleObject->SetClientSite(this);
|
|
659 |
}
|
|
660 |
|
|
661 |
IViewObject *spViewObject = 0;
|
|
662 |
m_spOleObject->QueryInterface(IID_IViewObject, (void**) &spViewObject);
|
|
663 |
|
|
664 |
m_spOleObject->Advise(this, &m_dwOleObject);
|
|
665 |
IAdviseSink *spAdviseSink = 0;
|
|
666 |
QueryInterface(IID_IAdviseSink, (void**)&spAdviseSink);
|
|
667 |
if (spAdviseSink && spViewObject) {
|
|
668 |
if (spViewObject)
|
|
669 |
spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);
|
|
670 |
spAdviseSink->Release();
|
|
671 |
}
|
|
672 |
if (spViewObject)
|
|
673 |
spViewObject->Release();
|
|
674 |
|
|
675 |
m_spOleObject->SetHostNames(OLESTR("AXWIN"), 0);
|
|
676 |
|
|
677 |
if (!(dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)) {
|
|
678 |
SIZEL hmSize;
|
|
679 |
hmSize.cx = MAP_PIX_TO_LOGHIM(250, widget->logicalDpiX());
|
|
680 |
hmSize.cy = MAP_PIX_TO_LOGHIM(250, widget->logicalDpiY());
|
|
681 |
|
|
682 |
m_spOleObject->SetExtent(DVASPECT_CONTENT, &hmSize);
|
|
683 |
m_spOleObject->GetExtent(DVASPECT_CONTENT, &hmSize);
|
|
684 |
|
|
685 |
sizehint.setWidth(MAP_LOGHIM_TO_PIX(hmSize.cx, widget->logicalDpiX()));
|
|
686 |
sizehint.setHeight(MAP_LOGHIM_TO_PIX(hmSize.cy, widget->logicalDpiY()));
|
|
687 |
showHost = true;
|
|
688 |
} else {
|
|
689 |
sizehint = QSize(0, 0);
|
|
690 |
host->hide();
|
|
691 |
}
|
|
692 |
if (!(dwMiscStatus & OLEMISC_NOUIACTIVATE)) {
|
|
693 |
host->setFocusPolicy(Qt::StrongFocus);
|
|
694 |
} else {
|
|
695 |
host->setFocusPolicy(Qt::NoFocus);
|
|
696 |
}
|
|
697 |
|
|
698 |
RECT rcPos = { host->x(), host->y(), host->x()+sizehint.width(), host->y()+sizehint.height() };
|
|
699 |
|
|
700 |
hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, 0, (IOleClientSite*)this, 0, host->winId(), &rcPos);
|
|
701 |
|
|
702 |
if (!m_spOleControl)
|
|
703 |
m_spOleObject->QueryInterface(IID_IOleControl, (void**)&m_spOleControl);
|
|
704 |
if (m_spOleControl) {
|
|
705 |
m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_BACKCOLOR);
|
|
706 |
m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_FORECOLOR);
|
|
707 |
m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_FONT);
|
|
708 |
m_spOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_USERMODE);
|
|
709 |
|
|
710 |
control_info.cb = sizeof(control_info);
|
|
711 |
m_spOleControl->GetControlInfo(&control_info);
|
|
712 |
}
|
|
713 |
|
|
714 |
BSTR userType;
|
|
715 |
HRESULT result = m_spOleObject->GetUserType(USERCLASSTYPE_SHORT, &userType);
|
|
716 |
if (result == S_OK) {
|
|
717 |
widget->setWindowTitle(QString::fromWCharArray(userType));
|
|
718 |
CoTaskMemFree(userType);
|
|
719 |
}
|
|
720 |
} else {
|
|
721 |
IObjectWithSite *spSite = 0;
|
|
722 |
widget->queryInterface(IID_IObjectWithSite, (void**)&spSite);
|
|
723 |
if (spSite) {
|
|
724 |
spSite->SetSite((IUnknown*)(IDispatch*)this);
|
|
725 |
spSite->Release();
|
|
726 |
}
|
|
727 |
}
|
|
728 |
|
|
729 |
host->resize(widget->size());
|
|
730 |
if (showHost)
|
|
731 |
host->show();
|
|
732 |
|
|
733 |
if (host->focusPolicy() != Qt::NoFocus) {
|
|
734 |
widget->setFocusProxy(host);
|
|
735 |
widget->setFocusPolicy(host->focusPolicy());
|
|
736 |
}
|
|
737 |
|
|
738 |
return true;
|
|
739 |
}
|
|
740 |
|
|
741 |
QAxClientSite::~QAxClientSite()
|
|
742 |
{
|
|
743 |
if (host) {
|
|
744 |
host->axhost = 0;
|
|
745 |
}
|
|
746 |
|
|
747 |
if (aggregatedObject)
|
|
748 |
aggregatedObject->the_object = 0;
|
|
749 |
delete aggregatedObject;
|
|
750 |
delete host;
|
|
751 |
}
|
|
752 |
|
|
753 |
void QAxClientSite::releaseAll()
|
|
754 |
{
|
|
755 |
if (m_spOleObject) {
|
|
756 |
m_spOleObject->SetClientSite(0);
|
|
757 |
m_spOleObject->Unadvise(m_dwOleObject);
|
|
758 |
m_spOleObject->Release();
|
|
759 |
}
|
|
760 |
m_spOleObject = 0;
|
|
761 |
if (m_spOleControl) m_spOleControl->Release();
|
|
762 |
m_spOleControl = 0;
|
|
763 |
if (m_spInPlaceObject) m_spInPlaceObject->Release();
|
|
764 |
m_spInPlaceObject = 0;
|
|
765 |
if (m_spInPlaceActiveObject) m_spInPlaceActiveObject->Release();
|
|
766 |
m_spInPlaceActiveObject = 0;
|
|
767 |
|
|
768 |
inPlaceObjectWindowless = false;
|
|
769 |
}
|
|
770 |
|
|
771 |
void QAxClientSite::deactivate()
|
|
772 |
{
|
|
773 |
if (m_spInPlaceObject) m_spInPlaceObject->InPlaceDeactivate();
|
|
774 |
// if this assertion fails the control didn't call OnInPlaceDeactivate
|
|
775 |
Q_ASSERT(m_spInPlaceObject == 0);
|
|
776 |
}
|
|
777 |
|
|
778 |
//**** IUnknown
|
|
779 |
unsigned long WINAPI QAxClientSite::AddRef()
|
|
780 |
{
|
|
781 |
return ++ref;
|
|
782 |
}
|
|
783 |
|
|
784 |
unsigned long WINAPI QAxClientSite::Release()
|
|
785 |
{
|
|
786 |
if (!--ref) {
|
|
787 |
delete this;
|
|
788 |
return 0;
|
|
789 |
}
|
|
790 |
return ref;
|
|
791 |
}
|
|
792 |
|
|
793 |
HRESULT WINAPI QAxClientSite::QueryInterface(REFIID iid, void **iface)
|
|
794 |
{
|
|
795 |
*iface = 0;
|
|
796 |
|
|
797 |
if (iid == IID_IUnknown) {
|
|
798 |
*iface = (IUnknown*)(IDispatch*)this;
|
|
799 |
} else {
|
|
800 |
HRESULT res = S_OK;
|
|
801 |
if (aggregatedObject)
|
|
802 |
res = aggregatedObject->queryInterface(iid, iface);
|
|
803 |
if (*iface)
|
|
804 |
return res;
|
|
805 |
}
|
|
806 |
|
|
807 |
if (!(*iface)) {
|
|
808 |
if (iid == IID_IDispatch)
|
|
809 |
*iface = (IDispatch*)this;
|
|
810 |
else if (iid == IID_IOleClientSite)
|
|
811 |
*iface = (IOleClientSite*)this;
|
|
812 |
else if (iid == IID_IOleControlSite)
|
|
813 |
*iface = (IOleControlSite*)this;
|
|
814 |
else if (iid == IID_IOleWindow)
|
|
815 |
*iface = (IOleWindow*)(IOleInPlaceSite*)this;
|
|
816 |
else if (iid == IID_IOleInPlaceSite)
|
|
817 |
*iface = (IOleInPlaceSite*)this;
|
|
818 |
#ifdef QAX_SUPPORT_WINDOWLESS
|
|
819 |
else if (iid == IID_IOleInPlaceSiteEx)
|
|
820 |
*iface = (IOleInPlaceSiteEx*)this;
|
|
821 |
else if (iid == IID_IOleInPlaceSiteWindowless)
|
|
822 |
*iface = (IOleInPlaceSiteWindowless*)this;
|
|
823 |
#endif
|
|
824 |
else if (iid == IID_IOleInPlaceFrame)
|
|
825 |
*iface = (IOleInPlaceFrame*)this;
|
|
826 |
else if (iid == IID_IOleInPlaceUIWindow)
|
|
827 |
*iface = (IOleInPlaceUIWindow*)this;
|
|
828 |
else if (iid == IID_IOleDocumentSite && canHostDocument)
|
|
829 |
*iface = (IOleDocumentSite*)this;
|
|
830 |
else if (iid == IID_IAdviseSink)
|
|
831 |
*iface = (IAdviseSink*)this;
|
|
832 |
}
|
|
833 |
if (!*iface)
|
|
834 |
return E_NOINTERFACE;
|
|
835 |
|
|
836 |
AddRef();
|
|
837 |
return S_OK;
|
|
838 |
}
|
|
839 |
|
|
840 |
bool qax_runsInDesignMode = false;
|
|
841 |
|
|
842 |
//**** IDispatch
|
|
843 |
HRESULT WINAPI QAxClientSite::Invoke(DISPID dispIdMember,
|
|
844 |
REFIID /*riid*/,
|
|
845 |
LCID /*lcid*/,
|
|
846 |
WORD /*wFlags*/,
|
|
847 |
DISPPARAMS * /*pDispParams*/,
|
|
848 |
VARIANT *pVarResult,
|
|
849 |
EXCEPINFO * /*pExcepInfo*/,
|
|
850 |
UINT * /*puArgErr*/)
|
|
851 |
{
|
|
852 |
if (!pVarResult)
|
|
853 |
return E_POINTER;
|
|
854 |
if (!widget || !host)
|
|
855 |
return E_UNEXPECTED;
|
|
856 |
|
|
857 |
switch(dispIdMember) {
|
|
858 |
case DISPID_AMBIENT_USERMODE:
|
|
859 |
pVarResult->vt = VT_BOOL;
|
|
860 |
pVarResult->boolVal = !qax_runsInDesignMode;
|
|
861 |
return S_OK;
|
|
862 |
|
|
863 |
case DISPID_AMBIENT_AUTOCLIP:
|
|
864 |
case DISPID_AMBIENT_SUPPORTSMNEMONICS:
|
|
865 |
pVarResult->vt = VT_BOOL;
|
|
866 |
pVarResult->boolVal = true;
|
|
867 |
return S_OK;
|
|
868 |
|
|
869 |
case DISPID_AMBIENT_SHOWHATCHING:
|
|
870 |
case DISPID_AMBIENT_SHOWGRABHANDLES:
|
|
871 |
case DISPID_AMBIENT_DISPLAYASDEFAULT:
|
|
872 |
case DISPID_AMBIENT_MESSAGEREFLECT:
|
|
873 |
pVarResult->vt = VT_BOOL;
|
|
874 |
pVarResult->boolVal = false;
|
|
875 |
return S_OK;
|
|
876 |
|
|
877 |
case DISPID_AMBIENT_DISPLAYNAME:
|
|
878 |
pVarResult->vt = VT_BSTR;
|
|
879 |
pVarResult->bstrVal = QStringToBSTR(widget->windowTitle());
|
|
880 |
return S_OK;
|
|
881 |
|
|
882 |
case DISPID_AMBIENT_FONT:
|
|
883 |
QVariantToVARIANT(widget->font(), *pVarResult);
|
|
884 |
return S_OK;
|
|
885 |
|
|
886 |
case DISPID_AMBIENT_BACKCOLOR:
|
|
887 |
pVarResult->vt = VT_UI4;
|
|
888 |
pVarResult->lVal = QColorToOLEColor(widget->palette().color(widget->backgroundRole()));
|
|
889 |
return S_OK;
|
|
890 |
|
|
891 |
case DISPID_AMBIENT_FORECOLOR:
|
|
892 |
pVarResult->vt = VT_UI4;
|
|
893 |
pVarResult->lVal = QColorToOLEColor(widget->palette().color(widget->foregroundRole()));
|
|
894 |
return S_OK;
|
|
895 |
|
|
896 |
case DISPID_AMBIENT_UIDEAD:
|
|
897 |
pVarResult->vt = VT_BOOL;
|
|
898 |
pVarResult->boolVal = !widget->isEnabled();
|
|
899 |
return S_OK;
|
|
900 |
|
|
901 |
default:
|
|
902 |
break;
|
|
903 |
}
|
|
904 |
|
|
905 |
return DISP_E_MEMBERNOTFOUND;
|
|
906 |
}
|
|
907 |
|
|
908 |
void QAxClientSite::emitAmbientPropertyChange(DISPID dispid)
|
|
909 |
{
|
|
910 |
if (m_spOleControl)
|
|
911 |
m_spOleControl->OnAmbientPropertyChange(dispid);
|
|
912 |
}
|
|
913 |
|
|
914 |
//**** IOleClientSite
|
|
915 |
HRESULT WINAPI QAxClientSite::SaveObject()
|
|
916 |
{
|
|
917 |
return E_NOTIMPL;
|
|
918 |
}
|
|
919 |
|
|
920 |
HRESULT WINAPI QAxClientSite::GetMoniker(DWORD, DWORD, IMoniker **ppmk)
|
|
921 |
{
|
|
922 |
if (!ppmk)
|
|
923 |
return E_POINTER;
|
|
924 |
|
|
925 |
*ppmk = 0;
|
|
926 |
return E_NOTIMPL;
|
|
927 |
}
|
|
928 |
|
|
929 |
HRESULT WINAPI QAxClientSite::GetContainer(LPOLECONTAINER *ppContainer)
|
|
930 |
{
|
|
931 |
if (!ppContainer)
|
|
932 |
return E_POINTER;
|
|
933 |
|
|
934 |
*ppContainer = 0;
|
|
935 |
return E_NOINTERFACE;
|
|
936 |
}
|
|
937 |
|
|
938 |
HRESULT WINAPI QAxClientSite::ShowObject()
|
|
939 |
{
|
|
940 |
return S_OK;
|
|
941 |
}
|
|
942 |
|
|
943 |
HRESULT WINAPI QAxClientSite::OnShowWindow(BOOL /*fShow*/)
|
|
944 |
{
|
|
945 |
return S_OK;
|
|
946 |
}
|
|
947 |
|
|
948 |
HRESULT WINAPI QAxClientSite::RequestNewObjectLayout()
|
|
949 |
{
|
|
950 |
return E_NOTIMPL;
|
|
951 |
}
|
|
952 |
|
|
953 |
//**** IOleControlSite
|
|
954 |
HRESULT WINAPI QAxClientSite::OnControlInfoChanged()
|
|
955 |
{
|
|
956 |
if (m_spOleControl)
|
|
957 |
m_spOleControl->GetControlInfo(&control_info);
|
|
958 |
|
|
959 |
return S_OK;
|
|
960 |
}
|
|
961 |
|
|
962 |
HRESULT WINAPI QAxClientSite::LockInPlaceActive(BOOL /*fLock*/)
|
|
963 |
{
|
|
964 |
AX_DEBUG(QAxClientSite::LockInPlaceActive);
|
|
965 |
return S_OK;
|
|
966 |
}
|
|
967 |
|
|
968 |
HRESULT WINAPI QAxClientSite::GetExtendedControl(IDispatch** ppDisp)
|
|
969 |
{
|
|
970 |
if (!ppDisp)
|
|
971 |
return E_POINTER;
|
|
972 |
|
|
973 |
*ppDisp = 0;
|
|
974 |
return E_NOTIMPL;
|
|
975 |
}
|
|
976 |
|
|
977 |
HRESULT WINAPI QAxClientSite::TransformCoords(POINTL* /*pPtlHimetric*/, POINTF* /*pPtfContainer*/, DWORD /*dwFlags*/)
|
|
978 |
{
|
|
979 |
return S_OK;
|
|
980 |
}
|
|
981 |
|
|
982 |
HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, DWORD /*grfModifiers*/)
|
|
983 |
{
|
|
984 |
if (lpMsg->message == WM_KEYDOWN && !lpMsg->wParam)
|
|
985 |
return S_OK;
|
|
986 |
|
|
987 |
bool ActiveQtDetected = false;
|
|
988 |
bool fromInProcServer = false;
|
|
989 |
#ifdef GWLP_USERDATA
|
|
990 |
LONG_PTR serverType = GetWindowLongPtr(lpMsg->hwnd, GWLP_USERDATA);
|
|
991 |
#else
|
|
992 |
LONG serverType = GetWindowLong(lpMsg->hwnd, GWL_USERDATA);
|
|
993 |
#endif
|
|
994 |
if (serverType == QAX_INPROC_SERVER) {
|
|
995 |
ActiveQtDetected = true;
|
|
996 |
fromInProcServer = true;
|
|
997 |
} else if (serverType == QAX_OUTPROC_SERVER) {
|
|
998 |
ActiveQtDetected = true;
|
|
999 |
fromInProcServer = false;
|
|
1000 |
}
|
|
1001 |
|
|
1002 |
eventTranslated = false;
|
|
1003 |
if (!ActiveQtDetected || !fromInProcServer) {
|
|
1004 |
// if the request is coming from an out-of-proc server or a non ActiveQt server,
|
|
1005 |
// we send the message to the host window. This will make sure this key event
|
|
1006 |
// comes to Qt for processing.
|
|
1007 |
SendMessage(host->winId(), lpMsg->message, lpMsg->wParam, lpMsg->lParam);
|
|
1008 |
if (ActiveQtDetected && !fromInProcServer) {
|
|
1009 |
// ActiveQt based servers will need further processing of the event
|
|
1010 |
// (eg. <SPACE> key for a checkbox), so we return false.
|
|
1011 |
return S_FALSE;
|
|
1012 |
}
|
|
1013 |
}
|
|
1014 |
// ActiveQt based in-processes-servers will handle the event properly, so
|
|
1015 |
// we dont need to send this key event to the host.
|
|
1016 |
return S_OK;
|
|
1017 |
}
|
|
1018 |
|
|
1019 |
HRESULT WINAPI QAxClientSite::OnFocus(BOOL bGotFocus)
|
|
1020 |
{
|
|
1021 |
AX_DEBUG(QAxClientSite::OnFocus);
|
|
1022 |
if (host) {
|
|
1023 |
host->hasFocus = bGotFocus;
|
|
1024 |
qApp->removeEventFilter(host);
|
|
1025 |
if (bGotFocus)
|
|
1026 |
qApp->installEventFilter(host);
|
|
1027 |
}
|
|
1028 |
return S_OK;
|
|
1029 |
}
|
|
1030 |
|
|
1031 |
HRESULT WINAPI QAxClientSite::ShowPropertyFrame()
|
|
1032 |
{
|
|
1033 |
return E_NOTIMPL;
|
|
1034 |
}
|
|
1035 |
|
|
1036 |
//**** IOleWindow
|
|
1037 |
HRESULT WINAPI QAxClientSite::GetWindow(HWND *phwnd)
|
|
1038 |
{
|
|
1039 |
if (!phwnd)
|
|
1040 |
return E_POINTER;
|
|
1041 |
|
|
1042 |
*phwnd = host->winId();
|
|
1043 |
return S_OK;
|
|
1044 |
}
|
|
1045 |
|
|
1046 |
HRESULT WINAPI QAxClientSite::ContextSensitiveHelp(BOOL fEnterMode)
|
|
1047 |
{
|
|
1048 |
if (fEnterMode)
|
|
1049 |
QWhatsThis::enterWhatsThisMode();
|
|
1050 |
else
|
|
1051 |
QWhatsThis::leaveWhatsThisMode();
|
|
1052 |
|
|
1053 |
return S_OK;
|
|
1054 |
}
|
|
1055 |
|
|
1056 |
//**** IOleInPlaceSite
|
|
1057 |
HRESULT WINAPI QAxClientSite::CanInPlaceActivate()
|
|
1058 |
{
|
|
1059 |
AX_DEBUG(QAxClientSite::CanInPlaceActivate);
|
|
1060 |
return S_OK;
|
|
1061 |
}
|
|
1062 |
|
|
1063 |
HRESULT WINAPI QAxClientSite::OnInPlaceActivate()
|
|
1064 |
{
|
|
1065 |
AX_DEBUG(QAxClientSite::OnInPlaceActivate);
|
|
1066 |
#if !defined(Q_OS_WINCE)
|
|
1067 |
OleLockRunning(m_spOleObject, true, false);
|
|
1068 |
#endif
|
|
1069 |
if (!m_spInPlaceObject) {
|
|
1070 |
/* ### disabled for now
|
|
1071 |
m_spOleObject->QueryInterface(IID_IOleInPlaceObjectWindowless, (void**) &m_spInPlaceObject);
|
|
1072 |
*/
|
|
1073 |
if (m_spInPlaceObject) {
|
|
1074 |
inPlaceObjectWindowless = true;
|
|
1075 |
} else {
|
|
1076 |
inPlaceObjectWindowless = false;
|
|
1077 |
m_spOleObject->QueryInterface(IID_IOleInPlaceObject, (void**) &m_spInPlaceObject);
|
|
1078 |
}
|
|
1079 |
}
|
|
1080 |
|
|
1081 |
return S_OK;
|
|
1082 |
}
|
|
1083 |
|
|
1084 |
HRESULT WINAPI QAxClientSite::OnUIActivate()
|
|
1085 |
{
|
|
1086 |
AX_DEBUG(QAxClientSite::OnUIActivate);
|
|
1087 |
return S_OK;
|
|
1088 |
}
|
|
1089 |
|
|
1090 |
HRESULT WINAPI QAxClientSite::GetWindowContext(IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
|
|
1091 |
{
|
|
1092 |
if (!ppFrame || !ppDoc || !lprcPosRect || !lprcClipRect || !lpFrameInfo)
|
|
1093 |
return E_POINTER;
|
|
1094 |
|
|
1095 |
QueryInterface(IID_IOleInPlaceFrame, (void**)ppFrame);
|
|
1096 |
QueryInterface(IID_IOleInPlaceUIWindow, (void**)ppDoc);
|
|
1097 |
|
|
1098 |
::GetClientRect(host->winId(), lprcPosRect);
|
|
1099 |
::GetClientRect(host->winId(), lprcClipRect);
|
|
1100 |
|
|
1101 |
lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
|
|
1102 |
lpFrameInfo->fMDIApp = false;
|
|
1103 |
lpFrameInfo->haccel = 0;
|
|
1104 |
lpFrameInfo->cAccelEntries = 0;
|
|
1105 |
lpFrameInfo->hwndFrame = widget ? widget->window()->winId() : 0;
|
|
1106 |
|
|
1107 |
return S_OK;
|
|
1108 |
}
|
|
1109 |
|
|
1110 |
HRESULT WINAPI QAxClientSite::Scroll(SIZE /*scrollExtant*/)
|
|
1111 |
{
|
|
1112 |
return S_FALSE;
|
|
1113 |
}
|
|
1114 |
|
|
1115 |
HRESULT WINAPI QAxClientSite::OnUIDeactivate(BOOL)
|
|
1116 |
{
|
|
1117 |
AX_DEBUG(QAxClientSite::OnUIDeactivate);
|
|
1118 |
if (host && host->hasFocus) {
|
|
1119 |
qApp->removeEventFilter(host);
|
|
1120 |
host->hasFocus = false;
|
|
1121 |
}
|
|
1122 |
return S_OK;
|
|
1123 |
}
|
|
1124 |
|
|
1125 |
HRESULT WINAPI QAxClientSite::OnInPlaceDeactivate()
|
|
1126 |
{
|
|
1127 |
AX_DEBUG(QAxClientSite::OnInPlaceDeactivate);
|
|
1128 |
if (m_spInPlaceObject)
|
|
1129 |
m_spInPlaceObject->Release();
|
|
1130 |
m_spInPlaceObject = 0;
|
|
1131 |
inPlaceObjectWindowless = false;
|
|
1132 |
#if !defined(Q_OS_WINCE)
|
|
1133 |
OleLockRunning(m_spOleObject, false, false);
|
|
1134 |
#endif
|
|
1135 |
|
|
1136 |
return S_OK;
|
|
1137 |
}
|
|
1138 |
|
|
1139 |
HRESULT WINAPI QAxClientSite::DiscardUndoState()
|
|
1140 |
{
|
|
1141 |
return S_OK;
|
|
1142 |
}
|
|
1143 |
|
|
1144 |
HRESULT WINAPI QAxClientSite::DeactivateAndUndo()
|
|
1145 |
{
|
|
1146 |
if (m_spInPlaceObject)
|
|
1147 |
m_spInPlaceObject->UIDeactivate();
|
|
1148 |
|
|
1149 |
return S_OK;
|
|
1150 |
}
|
|
1151 |
|
|
1152 |
HRESULT WINAPI QAxClientSite::OnPosRectChange(LPCRECT /*lprcPosRect*/)
|
|
1153 |
{
|
|
1154 |
AX_DEBUG(QAxClientSite::OnPosRectChange);
|
|
1155 |
// ###
|
|
1156 |
return S_OK;
|
|
1157 |
}
|
|
1158 |
|
|
1159 |
//**** IOleInPlaceFrame
|
|
1160 |
#if defined(Q_WS_WINCE)
|
|
1161 |
HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
|
|
1162 |
{
|
|
1163 |
return E_NOTIMPL;
|
|
1164 |
#else
|
|
1165 |
HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS lpMenuWidths)
|
|
1166 |
{
|
|
1167 |
AX_DEBUG(QAxClientSite::InsertMenus);
|
|
1168 |
QMenuBar *mb = menuBar;
|
|
1169 |
if (!mb)
|
|
1170 |
mb = qFindChild<QMenuBar*>(widget->window());
|
|
1171 |
if (!mb)
|
|
1172 |
return E_NOTIMPL;
|
|
1173 |
menuBar = mb;
|
|
1174 |
|
|
1175 |
QMenu *fileMenu = 0;
|
|
1176 |
QMenu *viewMenu = 0;
|
|
1177 |
QMenu *windowMenu = 0;
|
|
1178 |
QList<QAction*> actions = menuBar->actions();
|
|
1179 |
for (int i = 0; i < actions.count(); ++i) {
|
|
1180 |
QAction *action = actions.at(i);
|
|
1181 |
QString text = action->text().remove(QLatin1Char('&'));
|
|
1182 |
if (text == QLatin1String("File")) {
|
|
1183 |
fileMenu = action->menu();
|
|
1184 |
} else if (text == QLatin1String("View")) {
|
|
1185 |
viewMenu = action->menu();
|
|
1186 |
} else if (text == QLatin1String("Window")) {
|
|
1187 |
windowMenu = action->menu();
|
|
1188 |
}
|
|
1189 |
}
|
|
1190 |
if (fileMenu)
|
|
1191 |
lpMenuWidths->width[0] = fileMenu->actions().count();
|
|
1192 |
if (viewMenu)
|
|
1193 |
lpMenuWidths->width[2] = viewMenu->actions().count();
|
|
1194 |
if (windowMenu)
|
|
1195 |
lpMenuWidths->width[4] = windowMenu->actions().count();
|
|
1196 |
|
|
1197 |
return S_OK;
|
|
1198 |
#endif
|
|
1199 |
}
|
|
1200 |
|
|
1201 |
static int menuItemEntry(HMENU menu, int index, MENUITEMINFO item, QString &text, QPixmap &/*icon*/)
|
|
1202 |
{
|
|
1203 |
if (item.fType == MFT_STRING && item.cch) {
|
|
1204 |
wchar_t *titlebuf = new wchar_t[item.cch + 1];
|
|
1205 |
item.dwTypeData = titlebuf;
|
|
1206 |
item.cch++;
|
|
1207 |
::GetMenuItemInfo(menu, index, true, &item);
|
|
1208 |
text = QString::fromWCharArray(titlebuf);
|
|
1209 |
delete [] titlebuf;
|
|
1210 |
return MFT_STRING;
|
|
1211 |
}
|
|
1212 |
#if 0
|
|
1213 |
else if (item.fType == MFT_BITMAP) {
|
|
1214 |
HBITMAP hbm = (HBITMAP)LOWORD(item.hbmpItem);
|
|
1215 |
SIZE bmsize;
|
|
1216 |
GetBitmapDimensionEx(hbm, &bmsize);
|
|
1217 |
QPixmap pixmap(1,1);
|
|
1218 |
QSize sz(MAP_LOGHIM_TO_PIX(bmsize.cx, pixmap.logicalDpiX()),
|
|
1219 |
MAP_LOGHIM_TO_PIX(bmsize.cy, pixmap.logicalDpiY()));
|
|
1220 |
|
|
1221 |
pixmap.resize(bmsize.cx, bmsize.cy);
|
|
1222 |
if (!pixmap.isNull()) {
|
|
1223 |
HDC hdc = ::CreateCompatibleDC(pixmap.handle());
|
|
1224 |
::SelectObject(hdc, hbm);
|
|
1225 |
BOOL res = ::BitBlt(pixmap.handle(), 0, 0, pixmap.width(), pixmap.height(), hdc, 0, 0, SRCCOPY);
|
|
1226 |
::DeleteObject(hdc);
|
|
1227 |
}
|
|
1228 |
|
|
1229 |
icon = pixmap;
|
|
1230 |
}
|
|
1231 |
#endif
|
|
1232 |
return -1;
|
|
1233 |
}
|
|
1234 |
|
|
1235 |
#if !defined(Q_OS_WINCE)
|
|
1236 |
QMenu *QAxClientSite::generatePopup(HMENU subMenu, QWidget *parent)
|
|
1237 |
{
|
|
1238 |
QMenu *popup = 0;
|
|
1239 |
int count = GetMenuItemCount(subMenu);
|
|
1240 |
if (count)
|
|
1241 |
popup = new QMenu(parent);
|
|
1242 |
for (int i = 0; i < count; ++i) {
|
|
1243 |
MENUITEMINFO item;
|
|
1244 |
memset(&item, 0, sizeof(MENUITEMINFO));
|
|
1245 |
item.cbSize = sizeof(MENUITEMINFO);
|
|
1246 |
item.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU;
|
|
1247 |
::GetMenuItemInfo(subMenu, i, true, &item);
|
|
1248 |
|
|
1249 |
QAction *action = 0;
|
|
1250 |
QMenu *popupMenu = 0;
|
|
1251 |
if (item.fType == MFT_SEPARATOR) {
|
|
1252 |
action = popup->addSeparator();
|
|
1253 |
} else {
|
|
1254 |
QString text;
|
|
1255 |
QPixmap icon;
|
|
1256 |
QKeySequence accel;
|
|
1257 |
popupMenu = item.hSubMenu ? generatePopup(item.hSubMenu, popup) : 0;
|
|
1258 |
int res = menuItemEntry(subMenu, i, item, text, icon);
|
|
1259 |
|
|
1260 |
int lastSep = text.lastIndexOf(QRegExp(QLatin1String("[\\s]")));
|
|
1261 |
if (lastSep != -1) {
|
|
1262 |
QString keyString = text.right(text.length() - lastSep);
|
|
1263 |
accel = keyString;
|
|
1264 |
if ((int)accel)
|
|
1265 |
text = text.left(lastSep);
|
|
1266 |
}
|
|
1267 |
|
|
1268 |
if (popupMenu)
|
|
1269 |
popupMenu->setTitle(text);
|
|
1270 |
|
|
1271 |
switch (res) {
|
|
1272 |
case MFT_STRING:
|
|
1273 |
if (popupMenu)
|
|
1274 |
action = popup->addMenu(popupMenu);
|
|
1275 |
else
|
|
1276 |
action = popup->addAction(text);
|
|
1277 |
break;
|
|
1278 |
case MFT_BITMAP:
|
|
1279 |
if (popupMenu)
|
|
1280 |
action = popup->addMenu(popupMenu);
|
|
1281 |
else
|
|
1282 |
action = popup->addAction(icon, text);
|
|
1283 |
break;
|
|
1284 |
}
|
|
1285 |
|
|
1286 |
if (action) {
|
|
1287 |
if (int(accel))
|
|
1288 |
action->setShortcut(accel);
|
|
1289 |
if (!icon.isNull())
|
|
1290 |
action->setIcon(icon);
|
|
1291 |
}
|
|
1292 |
}
|
|
1293 |
|
|
1294 |
if (action) {
|
|
1295 |
OleMenuItem oleItem(subMenu, item.wID, popupMenu);
|
|
1296 |
menuItemMap.insert(action, oleItem);
|
|
1297 |
}
|
|
1298 |
}
|
|
1299 |
return popup;
|
|
1300 |
}
|
|
1301 |
#endif
|
|
1302 |
|
|
1303 |
#if defined(Q_OS_WINCE)
|
|
1304 |
HRESULT WINAPI QAxClientSite::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/)
|
|
1305 |
{
|
|
1306 |
return E_NOTIMPL;
|
|
1307 |
#else
|
|
1308 |
HRESULT WINAPI QAxClientSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
|
|
1309 |
{
|
|
1310 |
AX_DEBUG(QAxClientSite::SetMenu);
|
|
1311 |
|
|
1312 |
if (hmenuShared) {
|
|
1313 |
m_menuOwner = hwndActiveObject;
|
|
1314 |
QMenuBar *mb = menuBar;
|
|
1315 |
if (!mb)
|
|
1316 |
mb = qFindChild<QMenuBar*>(widget->window());
|
|
1317 |
if (!mb)
|
|
1318 |
return E_NOTIMPL;
|
|
1319 |
menuBar = mb;
|
|
1320 |
|
|
1321 |
int count = GetMenuItemCount(hmenuShared);
|
|
1322 |
for (int i = 0; i < count; ++i) {
|
|
1323 |
MENUITEMINFO item;
|
|
1324 |
memset(&item, 0, sizeof(MENUITEMINFO));
|
|
1325 |
item.cbSize = sizeof(MENUITEMINFO);
|
|
1326 |
item.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU;
|
|
1327 |
::GetMenuItemInfo(hmenuShared, i, true, &item);
|
|
1328 |
|
|
1329 |
QAction *action = 0;
|
|
1330 |
QMenu *popupMenu = 0;
|
|
1331 |
if (item.fType == MFT_SEPARATOR) {
|
|
1332 |
action = menuBar->addSeparator();
|
|
1333 |
} else {
|
|
1334 |
QString text;
|
|
1335 |
QPixmap icon;
|
|
1336 |
popupMenu = item.hSubMenu ? generatePopup(item.hSubMenu, menuBar) : 0;
|
|
1337 |
int res = menuItemEntry(hmenuShared, i, item, text, icon);
|
|
1338 |
|
|
1339 |
if (popupMenu)
|
|
1340 |
popupMenu->setTitle(text);
|
|
1341 |
|
|
1342 |
switch(res) {
|
|
1343 |
case MFT_STRING:
|
|
1344 |
if (popupMenu)
|
|
1345 |
action = menuBar->addMenu(popupMenu);
|
|
1346 |
else
|
|
1347 |
action = menuBar->addAction(text);
|
|
1348 |
break;
|
|
1349 |
case MFT_BITMAP:
|
|
1350 |
if (popupMenu)
|
|
1351 |
action = menuBar->addMenu(popupMenu);
|
|
1352 |
else
|
|
1353 |
action = menuBar->addAction(text);
|
|
1354 |
break;
|
|
1355 |
default:
|
|
1356 |
break;
|
|
1357 |
}
|
|
1358 |
if (action && !icon.isNull())
|
|
1359 |
action->setIcon(icon);
|
|
1360 |
}
|
|
1361 |
|
|
1362 |
if (action) {
|
|
1363 |
OleMenuItem oleItem(hmenuShared, item.wID, popupMenu);
|
|
1364 |
menuItemMap.insert(action, oleItem);
|
|
1365 |
}
|
|
1366 |
}
|
|
1367 |
if (count) {
|
|
1368 |
const QMetaObject *mbmo = menuBar->metaObject();
|
|
1369 |
int index = mbmo->indexOfSignal("triggered(QAction*)");
|
|
1370 |
Q_ASSERT(index != -1);
|
|
1371 |
menuBar->disconnect(SIGNAL(triggered(QAction*)), host);
|
|
1372 |
QMetaObject::connect(menuBar, index, host, index);
|
|
1373 |
}
|
|
1374 |
} else if (menuBar) {
|
|
1375 |
m_menuOwner = 0;
|
|
1376 |
QMap<QAction*, OleMenuItem>::Iterator it;
|
|
1377 |
for (it = menuItemMap.begin(); it != menuItemMap.end(); ++it) {
|
|
1378 |
QAction *action = it.key();
|
|
1379 |
delete action;
|
|
1380 |
}
|
|
1381 |
menuItemMap.clear();
|
|
1382 |
}
|
|
1383 |
|
|
1384 |
OleSetMenuDescriptor(holemenu, widget ? widget->window()->winId() : 0, m_menuOwner, this, m_spInPlaceActiveObject);
|
|
1385 |
return S_OK;
|
|
1386 |
#endif
|
|
1387 |
}
|
|
1388 |
|
|
1389 |
#if defined(Q_OS_WINCE)
|
|
1390 |
int QAxClientSite::qt_metacall(QMetaObject::Call /*call*/, int isignal, void ** /*argv*/)
|
|
1391 |
{
|
|
1392 |
return isignal;
|
|
1393 |
#else
|
|
1394 |
int QAxClientSite::qt_metacall(QMetaObject::Call call, int isignal, void **argv)
|
|
1395 |
{
|
|
1396 |
if (!m_spOleObject || call != QMetaObject::InvokeMetaMethod || !menuBar)
|
|
1397 |
return isignal;
|
|
1398 |
|
|
1399 |
if (isignal != menuBar->metaObject()->indexOfSignal("triggered(QAction*)"))
|
|
1400 |
return isignal;
|
|
1401 |
|
|
1402 |
QAction *action = *(QAction**)argv[1];
|
|
1403 |
// ###
|
|
1404 |
|
|
1405 |
OleMenuItem oleItem = menuItemMap.value(action);
|
|
1406 |
if (oleItem.hMenu)
|
|
1407 |
::PostMessage(m_menuOwner, WM_COMMAND, oleItem.id, 0);
|
|
1408 |
return -1;
|
|
1409 |
#endif
|
|
1410 |
}
|
|
1411 |
|
|
1412 |
|
|
1413 |
HRESULT WINAPI QAxClientSite::RemoveMenus(HMENU /*hmenuShared*/)
|
|
1414 |
{
|
|
1415 |
#if defined(Q_OS_WINCE)
|
|
1416 |
return E_NOTIMPL;
|
|
1417 |
#else
|
|
1418 |
AX_DEBUG(QAxClientSite::RemoveMenus);
|
|
1419 |
QMap<QAction*, OleMenuItem>::Iterator it;
|
|
1420 |
for (it = menuItemMap.begin(); it != menuItemMap.end(); ++it) {
|
|
1421 |
QAction *action = it.key();
|
|
1422 |
action->setVisible(false);
|
|
1423 |
delete action;
|
|
1424 |
}
|
|
1425 |
menuItemMap.clear();
|
|
1426 |
return S_OK;
|
|
1427 |
#endif
|
|
1428 |
}
|
|
1429 |
|
|
1430 |
HRESULT WINAPI QAxClientSite::SetStatusText(LPCOLESTR pszStatusText)
|
|
1431 |
{
|
|
1432 |
QStatusTipEvent tip(QString::fromWCharArray(pszStatusText));
|
|
1433 |
QApplication::sendEvent(widget, &tip);
|
|
1434 |
return S_OK;
|
|
1435 |
}
|
|
1436 |
|
|
1437 |
extern Q_GUI_EXPORT bool qt_win_ignoreNextMouseReleaseEvent;
|
|
1438 |
|
|
1439 |
HRESULT WINAPI QAxClientSite::EnableModeless(BOOL fEnable)
|
|
1440 |
{
|
|
1441 |
#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 |
|
|
1460 |
HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, WORD grfModifiers)
|
|
1461 |
{
|
|
1462 |
return TranslateAccelerator(lpMsg, (DWORD)grfModifiers);
|
|
1463 |
}
|
|
1464 |
|
|
1465 |
//**** IOleInPlaceUIWindow
|
|
1466 |
HRESULT 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 |
|
|
1484 |
HRESULT 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 |
|
|
1499 |
HRESULT 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 |
|
|
1541 |
HRESULT 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
|
|
1564 |
HRESULT 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 |
|
|
1600 |
QSize 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 |
|
|
1615 |
void 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 |
|
|
1635 |
QAxHostWidget::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 |
|
|
1646 |
QAxHostWidget::~QAxHostWidget()
|
|
1647 |
{
|
|
1648 |
if (axhost)
|
|
1649 |
axhost->reset(this);
|
|
1650 |
}
|
|
1651 |
|
|
1652 |
int 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 |
|
|
1659 |
void* 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 |
|
|
1667 |
QSize QAxHostWidget::sizeHint() const
|
|
1668 |
{
|
|
1669 |
return axhost ? axhost->sizeHint() : QWidget::sizeHint();
|
|
1670 |
}
|
|
1671 |
|
|
1672 |
QSize 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 |
|
|
1682 |
void 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 |
|
|
1708 |
void QAxHostWidget::resizeEvent(QResizeEvent *)
|
|
1709 |
{
|
|
1710 |
resizeObject();
|
|
1711 |
}
|
|
1712 |
|
|
1713 |
void QAxHostWidget::showEvent(QShowEvent *)
|
|
1714 |
{
|
|
1715 |
resizeObject();
|
|
1716 |
}
|
|
1717 |
|
|
1718 |
bool 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 |
|
|
1732 |
bool 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 |
|
|
1770 |
bool 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 |
|
|
1784 |
void 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 |
|
|
1797 |
void 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 |
|
|
1815 |
void 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 |
*/
|
|
1898 |
QAxWidget::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 |
*/
|
|
1909 |
QAxWidget::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 |
*/
|
|
1919 |
QAxWidget::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 |
*/
|
|
1930 |
QAxWidget::~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 |
*/
|
|
1947 |
bool 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 |
*/
|
|
1966 |
bool 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 |
*/
|
|
1984 |
bool 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 |
*/
|
|
2018 |
QAxAggregated *QAxWidget::createAggregate()
|
|
2019 |
{
|
|
2020 |
return 0;
|
|
2021 |
}
|
|
2022 |
|
|
2023 |
/*!
|
|
2024 |
\reimp
|
|
2025 |
|
|
2026 |
Shuts down the ActiveX control.
|
|
2027 |
*/
|
|
2028 |
void 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 |
*/
|
|
2068 |
bool 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 |
*/
|
|
2086 |
const QMetaObject *QAxWidget::metaObject() const
|
|
2087 |
{
|
|
2088 |
return QAxBase::metaObject();
|
|
2089 |
}
|
|
2090 |
|
|
2091 |
/*!
|
|
2092 |
\internal
|
|
2093 |
*/
|
|
2094 |
const QMetaObject *QAxWidget::parentMetaObject() const
|
|
2095 |
{
|
|
2096 |
return &QWidget::staticMetaObject;
|
|
2097 |
}
|
|
2098 |
|
|
2099 |
/*!
|
|
2100 |
\internal
|
|
2101 |
*/
|
|
2102 |
void *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 |
*/
|
|
2112 |
const char *QAxWidget::className() const
|
|
2113 |
{
|
|
2114 |
return "QAxWidget";
|
|
2115 |
}
|
|
2116 |
|
|
2117 |
/*!
|
|
2118 |
\internal
|
|
2119 |
*/
|
|
2120 |
int 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 |
*/
|
|
2131 |
QSize 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 |
*/
|
|
2145 |
QSize 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 |
*/
|
|
2159 |
void 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 |
*/
|
|
2186 |
void QAxWidget::resizeEvent(QResizeEvent *)
|
|
2187 |
{
|
|
2188 |
if (container)
|
|
2189 |
container->resize(size());
|
|
2190 |
}
|
|
2191 |
|
|
2192 |
/*!
|
|
2193 |
\reimp
|
|
2194 |
*/
|
|
2195 |
void 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 |
*/
|
|
2233 |
bool 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 |
|
|
2266 |
QT_END_NAMESPACE
|
|
2267 |
#endif // QT_NO_WIN_ACTIVEQT
|