Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
5.4 KiB

  1. #include "shellprv.h"
  2. #include "duiview.h"
  3. #include "duihost.h"
  4. // DUIAxHost Initialization
  5. HRESULT DUIAxHost::Create(UINT nCreate, UINT nActive, OUT DUIAxHost** ppElement)
  6. {
  7. *ppElement = NULL;
  8. DUIAxHost* pe = HNewAndZero<DUIAxHost>();
  9. if (!pe)
  10. return E_OUTOFMEMORY;
  11. HRESULT hr = pe->Initialize(nCreate, nActive);
  12. if (FAILED(hr))
  13. {
  14. pe->Destroy();
  15. }
  16. else
  17. {
  18. *ppElement = pe;
  19. }
  20. return hr;
  21. }
  22. HWND DUIAxHost::CreateHWND(HWND hwndParent)
  23. {
  24. return CreateWindowEx(0, CAxWindow::GetWndClassName(), NULL,
  25. WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  26. 0, 0, 0, 0, hwndParent, NULL, NULL, NULL);
  27. }
  28. HRESULT DUIAxHost::SetSite(IUnknown* punkSite)
  29. {
  30. CComPtr<IUnknown> spHost;
  31. HRESULT hr = AtlAxGetHost(GetHWND(), &spHost);
  32. if (SUCCEEDED(hr))
  33. {
  34. hr = IUnknown_SetSite(spHost, punkSite);
  35. }
  36. return hr;
  37. }
  38. void DUIAxHost::OnDestroy()
  39. {
  40. SetSite(NULL);
  41. HWNDHost::OnDestroy();
  42. ATOMICRELEASE(_pOleObject);
  43. }
  44. bool DUIAxHost::OnNotify(UINT nMsg, WPARAM wParam, LPARAM lParam, LRESULT* plRet)
  45. {
  46. switch (nMsg)
  47. {
  48. case WM_DESTROY:
  49. SetSite(NULL);
  50. break;
  51. }
  52. return HWNDHost::OnNotify(nMsg, wParam, lParam, plRet);
  53. }
  54. HRESULT DUIAxHost::AttachControl(IUnknown* punkObject)
  55. {
  56. if (NULL == GetHWND())
  57. return E_UNEXPECTED;
  58. if (NULL == punkObject)
  59. return E_INVALIDARG;
  60. ATOMICRELEASE(_pOleObject);
  61. HRESULT hr = punkObject->QueryInterface(IID_PPV_ARG(IOleObject, &_pOleObject));
  62. if (SUCCEEDED(hr))
  63. {
  64. CComPtr<IUnknown> spUnk;
  65. hr = AtlAxGetHost(GetHWND(), &spUnk);
  66. if (SUCCEEDED(hr))
  67. {
  68. CComPtr<IAxWinHostWindow> spDUIAxHostWindow;
  69. hr = spUnk->QueryInterface(&spDUIAxHostWindow);
  70. if (SUCCEEDED(hr))
  71. {
  72. hr = spDUIAxHostWindow->AttachControl(punkObject, GetHWND());
  73. }
  74. }
  75. }
  76. return hr;
  77. }
  78. ////////////////////////////////////////////////////////
  79. // DUIAxHost Rendering
  80. SIZE DUIAxHost::GetContentSize(int dConstW, int dConstH, Surface* psrf)
  81. {
  82. SIZE size = { 0, 0 };
  83. // Ask the attached ActiveX control for its preferred size
  84. if (NULL != _pOleObject)
  85. {
  86. SIZEL sizeT;
  87. if (SUCCEEDED(_pOleObject->GetExtent(DVASPECT_CONTENT, &sizeT)))
  88. {
  89. int dpiX;
  90. int dpiY;
  91. switch (psrf->GetType())
  92. {
  93. case Surface::stDC:
  94. {
  95. HDC hDC = CastHDC(psrf);
  96. dpiX = GetDeviceCaps(hDC, LOGPIXELSX);
  97. dpiY = GetDeviceCaps(hDC, LOGPIXELSX);
  98. }
  99. break;
  100. #ifdef GADGET_ENABLE_GDIPLUS
  101. case Surface::stGdiPlus:
  102. {
  103. Gdiplus::Graphics * pgpgr = CastGraphics(psrf);
  104. dpiX = (int)pgpgr->GetDpiX();
  105. dpiY = (int)pgpgr->GetDpiY();
  106. }
  107. break;
  108. #endif
  109. default:
  110. dpiX = dpiY = 96;
  111. break;
  112. }
  113. // Convert from HIMETRIC to pixels
  114. size.cx = (MAXLONG == sizeT.cx) ? MAXLONG : MulDiv(sizeT.cx, dpiX, 2540);
  115. size.cy = (MAXLONG == sizeT.cy) ? MAXLONG : MulDiv(sizeT.cy, dpiY, 2540);
  116. if (-1 != dConstW && size.cx > dConstW) size.cx = dConstW;
  117. if (-1 != dConstH && size.cy > dConstH) size.cy = dConstH;
  118. }
  119. }
  120. return size;
  121. }
  122. ////////////////////////////////////////////////////////
  123. // DUIAxHost Keyboard navigation
  124. void DUIAxHost::SetKeyFocus()
  125. {
  126. FakeTabEvent();
  127. // No matter what, we should continue with standard DUI operations.
  128. Element::SetKeyFocus();
  129. }
  130. void DUIAxHost::OnEvent(Event* pEvent)
  131. {
  132. bool fHandled = false;
  133. if (pEvent->nStage == GMF_DIRECT && pEvent->uidType == Element::KeyboardNavigate) {
  134. int iNavDir = ((KeyboardNavigateEvent*) pEvent)->iNavDir;
  135. if (((iNavDir & NAV_NEXT) == NAV_NEXT) || ((iNavDir & NAV_PREV) == NAV_PREV)) {
  136. fHandled = FakeTabEvent();
  137. } else {
  138. // Handle other types of navigation here... (home/end/etc)
  139. }
  140. }
  141. // Continue with standard DUI operation if the navigation event wasn't handled
  142. // by our contained ActiveX control.
  143. if (!fHandled) {
  144. Element::OnEvent(pEvent);
  145. }
  146. }
  147. bool DUIAxHost::FakeTabEvent()
  148. {
  149. bool fHandled = false;
  150. MSG msg;
  151. ZeroMemory(&msg, sizeof(msg));
  152. msg.message = WM_KEYDOWN;
  153. msg.wParam = VK_TAB;
  154. msg.lParam = 1;
  155. // Note: we probably should do something to respect navoigating forward
  156. // or backwards. The ActiveX control needs to know if it should activate
  157. // the first or last tab stop. For now it will only reliably
  158. // activate the first one. If it checks the keyboard Shift state
  159. // it will probably get it right, but not 100% guaranteed.
  160. if(SendMessage(GetHWND(), WM_FORWARDMSG, 0, (LPARAM)&msg)) {
  161. fHandled = true;
  162. }
  163. return fHandled;
  164. }
  165. // Define class info with type and base type, set static class pointer
  166. IClassInfo* DUIAxHost::Class = NULL;
  167. HRESULT DUIAxHost::Register()
  168. {
  169. return ClassInfo<DUIAxHost,HWNDHost>::Register(L"DUIAxHost", NULL, 0);
  170. }
  171. HRESULT DUIAxHost::GetAccessibleImpl(IAccessible ** ppAccessible)
  172. {
  173. return CreateStdAccessibleObject(GetHWND(), OBJID_CLIENT, IID_PPV_ARG(IAccessible, ppAccessible));
  174. }