|
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 |