Leaked source code of windows server 2003
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.

1938 lines
46 KiB

  1. #include "precomp.h"
  2. #define __MARS_INLINE_FAST_IS_EQUAL_GUID
  3. #include "mcinc.h"
  4. #include "marswin.h"
  5. #include <exdispid.h>
  6. #include "parser\marsload.h"
  7. #include "panel.h"
  8. #include "place.h"
  9. #include <strsafe.h>
  10. // CLASS_CMarsWindow = {172AF160-5CD4-11d3-97FA-00C04F45D0B3}
  11. const GUID CLASS_CMarsWindow = { 0x172af160, 0x5cd4, 0x11d3, { 0x97, 0xfa, 0x0, 0xc0, 0x4f, 0x45, 0xd0, 0xb3 } };
  12. // CLASS_CMarsDocument = {E0C4E3A8-20D6-47d6-87FB-0A43452117BA}
  13. const GUID CLASS_CMarsDocument = { 0xe0c4e3a8, 0x20d6, 0x47d6, { 0x87, 0xfb, 0xa, 0x43, 0x45, 0x21, 0x17, 0xba } };
  14. #define WZ_WINDOWPLACEMENT L"WindowPlacement\\%d_%d_%s"
  15. #define WZ_POSITIONMAX L"Maximized"
  16. #define WZ_POSITIONRECT L"Rect"
  17. static void combineMin( long& out, long in1, long in2 )
  18. {
  19. if(in1 > 0)
  20. {
  21. out = (in2 > 0) ? in2 + in1 : in1;
  22. }
  23. else
  24. {
  25. out = in2;
  26. }
  27. }
  28. static void combineMax( long& out, long in1, long in2 )
  29. {
  30. if(in1 < 0 || in2 < 0)
  31. {
  32. out = -1; // Don't care...
  33. }
  34. else
  35. {
  36. out = in2 + in1;
  37. }
  38. }
  39. static void selectMin( long& out, long in1, long in2 )
  40. {
  41. if(in1 < 0)
  42. {
  43. out = in2;
  44. }
  45. else if(in2 < 0)
  46. {
  47. out = in1;
  48. }
  49. else
  50. {
  51. out = max( in1, in2 );
  52. }
  53. }
  54. static void selectMax( long& out, long in1, long in2 )
  55. {
  56. if(in1 < 0)
  57. {
  58. out = in2;
  59. }
  60. else if(in2 < 0)
  61. {
  62. out = in1;
  63. }
  64. else
  65. {
  66. out = min( in1, in2 );
  67. }
  68. }
  69. static BOOL WriteWindowPosition(CRegistryKey &regkey, RECT *prc, BOOL fMaximized)
  70. {
  71. return ERROR_SUCCESS == regkey.SetBoolValue(fMaximized, WZ_POSITIONMAX)
  72. && ERROR_SUCCESS == regkey.SetBinaryValue(prc, sizeof(*prc), WZ_POSITIONRECT);
  73. }
  74. //==================================================================
  75. //
  76. // CMarsDocument implementation
  77. //
  78. //==================================================================
  79. CMarsDocument::CMarsDocument()
  80. {
  81. }
  82. CMarsDocument::~CMarsDocument()
  83. {
  84. }
  85. HRESULT CMarsWindow::Passivate()
  86. {
  87. return CMarsComObject::Passivate();
  88. }
  89. HRESULT CMarsDocument::DoPassivate()
  90. {
  91. m_spPanels.PassivateAndRelease();
  92. m_spPlaces.PassivateAndRelease();
  93. m_spMarsWindow.Release();
  94. m_spHostPanel.Release();
  95. m_cwndDocument.Detach();
  96. return S_OK;
  97. }
  98. IMPLEMENT_ADDREF_RELEASE(CMarsDocument);
  99. STDMETHODIMP CMarsDocument::QueryInterface(REFIID iid, void **ppvObject)
  100. {
  101. HRESULT hr;
  102. ATLASSERT(ppvObject);
  103. if(iid == IID_IUnknown ||
  104. iid == IID_IServiceProvider )
  105. {
  106. *ppvObject = SAFECAST(this, IServiceProvider *);
  107. }
  108. else if(iid == CLASS_CMarsDocument)
  109. {
  110. *ppvObject = SAFECAST(this, CMarsDocument *);
  111. }
  112. else
  113. {
  114. *ppvObject = NULL;
  115. }
  116. if(*ppvObject)
  117. {
  118. AddRef();
  119. hr = S_OK;
  120. }
  121. else
  122. {
  123. hr = E_NOINTERFACE;
  124. }
  125. return hr;
  126. }
  127. HRESULT CMarsDocument::Init(CMarsWindow *pMarsWindow, CMarsPanel *pHostPanel)
  128. {
  129. ATLASSERT(pMarsWindow);
  130. m_spMarsWindow = pMarsWindow;
  131. m_spHostPanel = pHostPanel;
  132. if(pHostPanel)
  133. {
  134. m_cwndDocument.Attach(m_spHostPanel->Window()->m_hWnd);
  135. }
  136. else
  137. {
  138. m_cwndDocument.Attach(m_spMarsWindow->m_hWnd);
  139. }
  140. m_spPlaces.Attach(new CPlaceCollection(this));
  141. m_spPanels.Attach(new CPanelCollection(this));
  142. return (m_spMarsWindow && m_spPanels && m_spPlaces) ? S_OK : E_FAIL;
  143. }
  144. // static
  145. HRESULT CMarsDocument::CreateInstance(CMarsWindow *pMarsWindow, CMarsPanel *pHostPanel, CMarsDocument **ppObj)
  146. {
  147. ATLASSERT(pMarsWindow && ppObj && (*ppObj==NULL));
  148. *ppObj=NULL;
  149. if(pMarsWindow)
  150. {
  151. CMarsDocument *pDoc;
  152. pDoc = new CMarsDocument();
  153. if(pDoc)
  154. {
  155. if(SUCCEEDED(pDoc->Init(pMarsWindow, pHostPanel)))
  156. {
  157. *ppObj = pDoc;
  158. }
  159. else
  160. {
  161. pDoc->Passivate();
  162. pDoc->Release();
  163. }
  164. }
  165. }
  166. return (*ppObj) ? S_OK : E_FAIL;
  167. }
  168. // IServiceProvider
  169. HRESULT CMarsDocument::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  170. {
  171. HRESULT hr = E_FAIL;
  172. *ppv = NULL;
  173. if(!IsPassive())
  174. {
  175. if(guidService == SID_SMarsDocument)
  176. {
  177. hr = QueryInterface(riid, ppv);
  178. }
  179. }
  180. return hr;
  181. }
  182. HRESULT CMarsDocument::GetPlaces(IMarsPlaceCollection **ppPlaces)
  183. {
  184. ATLASSERT(ppPlaces);
  185. ATLASSERT(!IsPassive());
  186. if(m_spPlaces)
  187. {
  188. return m_spPlaces.QueryInterface(ppPlaces);
  189. }
  190. *ppPlaces = NULL;
  191. return E_FAIL;
  192. }
  193. HRESULT CMarsDocument::ReadPanelDefinition(LPCWSTR pwszUrl)
  194. {
  195. FAIL_AFTER_PASSIVATE();
  196. HRESULT hr;
  197. GetPanels()->lockLayout();
  198. if(pwszUrl)
  199. {
  200. hr = CMMFParser::MMFToMars(pwszUrl, this);
  201. }
  202. else
  203. {
  204. hr = E_FAIL;
  205. }
  206. GetPanels()->unlockLayout();
  207. return hr;
  208. }
  209. void CMarsDocument::ForwardMessageToChildren(UINT uMsg, WPARAM wParam, LPARAM lParam)
  210. {
  211. CPanelCollection* panels = GetPanels();
  212. if(panels)
  213. {
  214. for(int i=0; i < panels->GetSize(); i++)
  215. {
  216. CMarsPanel* pPanel = (*panels)[i];
  217. if(pPanel) pPanel->ForwardMessage(uMsg, wParam, lParam);
  218. }
  219. }
  220. }
  221. //==================================================================
  222. //
  223. // CMarsWindow implementation
  224. //
  225. //==================================================================
  226. CMarsWindow::CMarsWindow()
  227. {
  228. m_fShowTitleBar = TRUE;
  229. m_fEnableModeless = TRUE;
  230. m_fLayoutLocked = FALSE;
  231. }
  232. CMarsWindow::~CMarsWindow()
  233. {
  234. if(m_hAccel)
  235. {
  236. DestroyAcceleratorTable(m_hAccel);
  237. }
  238. }
  239. HRESULT CMarsWindow::DoPassivate()
  240. {
  241. (void)NotifyHost(MARSHOST_ON_WIN_PASSIVATE, SAFECAST(this, IMarsWindowOM *), 0);
  242. CMarsDocument::DoPassivate();
  243. if(IsWindow())
  244. {
  245. DestroyWindow();
  246. }
  247. m_spMarsHost.Release();
  248. return S_OK;
  249. }
  250. IMPLEMENT_ADDREF_RELEASE(CMarsWindow);
  251. STDMETHODIMP CMarsWindow::QueryInterface(REFIID iid, void **ppvObject)
  252. {
  253. HRESULT hr;
  254. ATLASSERT(ppvObject);
  255. if(iid == IID_IMarsWindowOM ||
  256. iid == IID_IDispatch ||
  257. iid == IID_IUnknown )
  258. {
  259. *ppvObject = SAFECAST(this, IMarsWindowOM *);
  260. }
  261. else if(iid == IID_IOleWindow ||
  262. iid == IID_IOleInPlaceUIWindow ||
  263. iid == IID_IOleInPlaceFrame )
  264. {
  265. *ppvObject = SAFECAST(this, IOleInPlaceFrame *);
  266. }
  267. else if(iid == IID_IServiceProvider)
  268. {
  269. *ppvObject = SAFECAST(this, IServiceProvider *);
  270. }
  271. else if(iid == IID_IProfferService)
  272. {
  273. *ppvObject = SAFECAST(this, IProfferService *);
  274. }
  275. else if(iid == CLASS_CMarsWindow)
  276. {
  277. *ppvObject = SAFECAST(this, CMarsWindow *);
  278. }
  279. else
  280. {
  281. *ppvObject = NULL;
  282. }
  283. if(*ppvObject)
  284. {
  285. AddRef();
  286. hr = S_OK;
  287. }
  288. else
  289. {
  290. hr = CMarsDocument::QueryInterface(iid, ppvObject);
  291. }
  292. return hr;
  293. }
  294. //
  295. // Static creation function
  296. //
  297. HRESULT CMarsWindow::CreateInstance(IMarsHost *pMarsHost, MARSTHREADPARAM *pThreadParam, CMarsWindow **ppObj)
  298. {
  299. ATLASSERT(pThreadParam && ppObj && (*ppObj==NULL));
  300. *ppObj=NULL;
  301. if(pThreadParam)
  302. {
  303. CComClassPtr<CMarsWindow> spWin;
  304. spWin.Attach(new CMarsWindow());
  305. if(spWin)
  306. {
  307. if(pThreadParam->pwszFirstPlace)
  308. {
  309. spWin->m_bstrFirstPlace = pThreadParam->pwszFirstPlace;
  310. }
  311. if(SUCCEEDED(spWin->Init(pMarsHost, pThreadParam)) &&
  312. SUCCEEDED(spWin->Startup() ) )
  313. {
  314. *ppObj = spWin.Detach();
  315. }
  316. else
  317. {
  318. spWin.PassivateAndRelease();
  319. }
  320. }
  321. }
  322. return (*ppObj) ? S_OK : E_FAIL;
  323. }
  324. HRESULT CMarsWindow::Init(IMarsHost *pMarsHost, MARSTHREADPARAM *pThreadParam)
  325. {
  326. HRESULT hr;
  327. m_pThreadParam = pThreadParam;
  328. m_spMarsHost = pMarsHost;
  329. Create(NULL,
  330. rcDefault,
  331. GetThreadParam()->pwszTitle,
  332. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN
  333. );
  334. hr = CMarsDocument::Init(this, NULL);
  335. if(SUCCEEDED(hr))
  336. {
  337. CGlobalSettingsRegKey regkey;
  338. WINDOWPLACEMENT wp; wp.length = sizeof(wp);
  339. BOOL fMaximized;
  340. GetWindowPlacement( &wp );
  341. if(GetThreadParam()->dwFlags & MTF_MANAGE_WINDOW_SIZE)
  342. {
  343. if(InitWindowPosition( regkey, FALSE ))
  344. {
  345. LoadWindowPosition( regkey, TRUE, wp, fMaximized );
  346. }
  347. }
  348. if(SUCCEEDED(NotifyHost( MARSHOST_ON_WIN_SETPOS, SAFECAST(this, IMarsWindowOM *), (LPARAM)&wp )))
  349. {
  350. // Always make sure the window is fully on-screen
  351. BoundWindowRectToMonitor( m_hWnd, &wp.rcNormalPosition );
  352. }
  353. if(wp.showCmd == SW_MAXIMIZE)
  354. {
  355. m_fStartMaximized = true;
  356. }
  357. wp.showCmd = SW_HIDE;
  358. //// if(GetThreadParam()->dwFlags & MTF_DONT_SHOW_WINDOW)
  359. //// {
  360. //// wp.showCmd = SW_HIDE;
  361. //// }
  362. if(GetThreadParam()->dwFlags & MTF_MANAGE_WINDOW_SIZE)
  363. {
  364. // Make the next Mars window try and appear at the current location.
  365. WriteWindowPosition( regkey, &wp.rcNormalPosition, fMaximized );
  366. }
  367. SetWindowPlacement( &wp );
  368. }
  369. if(SUCCEEDED(hr))
  370. {
  371. hr = NotifyHost( MARSHOST_ON_WIN_INIT, SAFECAST(this, IMarsWindowOM *), (LPARAM)m_hWnd );
  372. }
  373. if(SUCCEEDED(hr))
  374. {
  375. hr = ReadPanelDefinition(GetThreadParam()->pwszPanelURL);
  376. }
  377. return hr;
  378. }
  379. HRESULT CMarsWindow::Startup()
  380. {
  381. HRESULT hr;
  382. if(SUCCEEDED(hr = NotifyHost( MARSHOST_ON_WIN_READY, SAFECAST(this, IMarsWindowOM *), 0 )))
  383. {
  384. if(hr == S_FALSE)
  385. {
  386. ; // Host has taken care of the startup.
  387. }
  388. else
  389. {
  390. CComClassPtr<CMarsPlace> spPlace;
  391. if(SUCCEEDED(hr = GetPlaces()->GetPlace( m_bstrFirstPlace, &spPlace )))
  392. {
  393. hr = spPlace->transitionTo();
  394. }
  395. }
  396. }
  397. return hr;
  398. }
  399. // IServiceProvider
  400. HRESULT CMarsWindow::QueryService(REFGUID guidService, REFIID riid, void **ppv)
  401. {
  402. HRESULT hr = E_FAIL;
  403. *ppv = NULL;
  404. if(!IsPassive())
  405. {
  406. if(guidService == SID_SProfferService ||
  407. guidService == SID_SMarsWindow ||
  408. guidService == SID_STopWindow )
  409. {
  410. hr = QueryInterface(riid, ppv);
  411. }
  412. else
  413. {
  414. hr = IProfferServiceImpl::QueryService(guidService, riid, ppv);
  415. if(FAILED(hr))
  416. {
  417. hr = CMarsDocument::QueryService(guidService, riid, ppv);
  418. if(FAILED(hr))
  419. {
  420. hr = IUnknown_QueryService(m_spMarsHost, guidService, riid, ppv);
  421. }
  422. }
  423. }
  424. }
  425. return hr;
  426. }
  427. // IMarsWindowOM
  428. STDMETHODIMP CMarsWindow::get_active(VARIANT_BOOL *pbActive)
  429. {
  430. HRESULT hr = E_INVALIDARG;
  431. if(API_IsValidWritePtr( pbActive ))
  432. {
  433. if(VerifyNotPassive( &hr ))
  434. {
  435. *pbActive = VARIANT_BOOLIFY(IsWindowActive());
  436. hr = S_OK;
  437. }
  438. else
  439. {
  440. *pbActive = VARIANT_FALSE;
  441. }
  442. }
  443. return hr;
  444. }
  445. STDMETHODIMP CMarsWindow::get_minimized(VARIANT_BOOL *pbMinimized)
  446. {
  447. HRESULT hr = E_INVALIDARG;
  448. if(API_IsValidWritePtr( pbMinimized ))
  449. {
  450. if(VerifyNotPassive( &hr ))
  451. {
  452. *pbMinimized = IsIconic() ? VARIANT_TRUE : VARIANT_FALSE;
  453. hr = S_OK;
  454. }
  455. else
  456. {
  457. *pbMinimized = VARIANT_FALSE;
  458. }
  459. }
  460. return hr;
  461. }
  462. STDMETHODIMP CMarsWindow::put_minimized(VARIANT_BOOL bMinimized)
  463. {
  464. ATLASSERT(IsValidVariantBoolVal(bMinimized));
  465. HRESULT hr = S_OK;
  466. if(VerifyNotPassive( &hr ))
  467. {
  468. if(!!IsIconic() != !!bMinimized)
  469. {
  470. SendMessage(WM_SYSCOMMAND, (bMinimized ? SC_MINIMIZE : SC_RESTORE), 0);
  471. }
  472. else
  473. {
  474. hr = S_FALSE;
  475. }
  476. }
  477. return hr;
  478. }
  479. STDMETHODIMP CMarsWindow::get_maximized(VARIANT_BOOL *pbMaximized)
  480. {
  481. HRESULT hr = E_INVALIDARG;
  482. if(API_IsValidWritePtr( pbMaximized ))
  483. {
  484. if(VerifyNotPassive( &hr ))
  485. {
  486. *pbMaximized = IsZoomed() ? VARIANT_TRUE : VARIANT_FALSE;
  487. hr = S_OK;
  488. }
  489. else
  490. {
  491. *pbMaximized = VARIANT_FALSE;
  492. }
  493. }
  494. return hr;
  495. }
  496. STDMETHODIMP CMarsWindow::put_maximized(VARIANT_BOOL bMaximized)
  497. {
  498. ATLASSERT(IsValidVariantBoolVal(bMaximized));
  499. HRESULT hr = S_OK;
  500. if(VerifyNotPassive( &hr ))
  501. {
  502. DWORD dwStyle = ::GetWindowLong( m_hWnd, GWL_STYLE );
  503. DWORD dwNewStyle = dwStyle | (WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX);
  504. if(dwStyle != dwNewStyle)
  505. {
  506. ::SetWindowLong( m_hWnd, GWL_STYLE, dwNewStyle );
  507. }
  508. if(!!IsZoomed() != !!bMaximized)
  509. {
  510. SendMessage(WM_SYSCOMMAND, (bMaximized ? SC_MAXIMIZE : SC_RESTORE), 0);
  511. }
  512. else
  513. {
  514. hr = S_FALSE;
  515. }
  516. }
  517. return hr;
  518. }
  519. STDMETHODIMP CMarsWindow::get_title(BSTR *pbstrTitle)
  520. {
  521. HRESULT hr = E_INVALIDARG;
  522. if(API_IsValidWritePtr(pbstrTitle))
  523. {
  524. if(VerifyNotPassive(&hr))
  525. {
  526. int nLen = (int)SendMessage(WM_GETTEXTLENGTH, 0, 0);
  527. // SysAllocStringLen adds 1 for the NULL terminator
  528. *pbstrTitle = SysAllocStringLen(NULL, nLen);
  529. if(*pbstrTitle)
  530. {
  531. GetWindowText(*pbstrTitle, nLen + 1);
  532. hr = S_OK;
  533. }
  534. else
  535. {
  536. hr = E_OUTOFMEMORY;
  537. }
  538. }
  539. else
  540. {
  541. *pbstrTitle = NULL;
  542. }
  543. }
  544. return hr;
  545. }
  546. STDMETHODIMP CMarsWindow::put_title(BSTR bstrTitle)
  547. {
  548. HRESULT hr = E_INVALIDARG;
  549. if(API_IsValidBstr(bstrTitle))
  550. {
  551. if(VerifyNotPassive(&hr))
  552. {
  553. // TODO: If the text is not displayable with the current system font
  554. // we need to come up with something legible.
  555. SetWindowText(bstrTitle);
  556. hr = S_OK;
  557. }
  558. }
  559. return hr;
  560. }
  561. STDMETHODIMP CMarsWindow::get_height(long *plHeight)
  562. {
  563. HRESULT hr = E_INVALIDARG;
  564. if(API_IsValidWritePtr(plHeight))
  565. {
  566. if(VerifyNotPassive(&hr))
  567. {
  568. hr = SCRIPT_ERROR;
  569. RECT rc;
  570. if(GetWindowRect(&rc))
  571. {
  572. *plHeight = RECTHEIGHT(rc);
  573. hr = S_OK;
  574. }
  575. }
  576. }
  577. return hr;
  578. }
  579. STDMETHODIMP CMarsWindow::put_height(long lHeight)
  580. {
  581. HRESULT hr = SCRIPT_ERROR;
  582. if(VerifyNotPassive(&hr))
  583. {
  584. RECT rc;
  585. if(GetWindowRect( &rc ) && SetWindowPos( NULL, 0, 0, RECTWIDTH(rc), lHeight, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE ))
  586. {
  587. hr = S_OK;
  588. }
  589. }
  590. return hr;
  591. }
  592. STDMETHODIMP CMarsWindow::get_width(long *plWidth)
  593. {
  594. HRESULT hr = E_INVALIDARG;
  595. if(API_IsValidWritePtr(plWidth))
  596. {
  597. if(VerifyNotPassive(&hr))
  598. {
  599. hr = SCRIPT_ERROR;
  600. RECT rc;
  601. if(GetWindowRect(&rc))
  602. {
  603. *plWidth = RECTWIDTH(rc);
  604. hr = S_OK;
  605. }
  606. }
  607. }
  608. return hr;
  609. }
  610. STDMETHODIMP CMarsWindow::put_width(long lWidth)
  611. {
  612. HRESULT hr = SCRIPT_ERROR;
  613. if(VerifyNotPassive(&hr))
  614. {
  615. RECT rc;
  616. if(GetWindowRect( &rc ) && SetWindowPos( NULL, 0, 0, lWidth, RECTHEIGHT(rc), SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE ))
  617. {
  618. hr = S_OK;
  619. }
  620. }
  621. return hr;
  622. }
  623. STDMETHODIMP CMarsWindow::get_x(long *plX)
  624. {
  625. HRESULT hr = E_INVALIDARG;
  626. if(API_IsValidWritePtr(plX))
  627. {
  628. if(VerifyNotPassive(&hr))
  629. {
  630. hr = SCRIPT_ERROR;
  631. RECT rc;
  632. if(GetWindowRect(&rc))
  633. {
  634. *plX = rc.left;
  635. hr = S_OK;
  636. }
  637. }
  638. }
  639. return hr;
  640. }
  641. STDMETHODIMP CMarsWindow::put_x(long lX)
  642. {
  643. HRESULT hr = SCRIPT_ERROR;
  644. if(VerifyNotPassive( &hr ))
  645. {
  646. RECT rc;
  647. if(GetWindowRect( &rc ) && SetWindowPos( NULL, lX, rc.top, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE ))
  648. {
  649. hr = S_OK;
  650. }
  651. }
  652. return hr;
  653. }
  654. STDMETHODIMP CMarsWindow::get_y(long *plY)
  655. {
  656. HRESULT hr = E_INVALIDARG;
  657. if(API_IsValidWritePtr(plY))
  658. {
  659. if(VerifyNotPassive(&hr))
  660. {
  661. hr = SCRIPT_ERROR;
  662. RECT rc;
  663. if(GetWindowRect(&rc))
  664. {
  665. *plY = rc.top;
  666. hr = S_OK;
  667. }
  668. }
  669. }
  670. return hr;
  671. }
  672. STDMETHODIMP CMarsWindow::put_y(long lY)
  673. {
  674. HRESULT hr = SCRIPT_ERROR;
  675. if(VerifyNotPassive( &hr ))
  676. {
  677. RECT rc;
  678. if(GetWindowRect( &rc ) && SetWindowPos( NULL, rc.left, lY, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE ))
  679. {
  680. hr = S_OK;
  681. }
  682. }
  683. return hr;
  684. }
  685. STDMETHODIMP CMarsWindow::get_visible(VARIANT_BOOL *pbVisible)
  686. {
  687. HRESULT hr = E_INVALIDARG;
  688. if(API_IsValidWritePtr(pbVisible))
  689. {
  690. if(VerifyNotPassive(&hr))
  691. {
  692. *pbVisible = IsWindowVisible() ? VARIANT_TRUE : VARIANT_FALSE;
  693. hr = S_OK;
  694. }
  695. }
  696. return hr;
  697. }
  698. STDMETHODIMP CMarsWindow::put_visible(VARIANT_BOOL bVisible)
  699. {
  700. HRESULT hr = SCRIPT_ERROR;
  701. if(VerifyNotPassive(&hr))
  702. {
  703. if(bVisible)
  704. {
  705. if(m_fUIPanelsReady)
  706. {
  707. DoShowWindow(SW_SHOW);
  708. }
  709. else
  710. {
  711. // Our UI hasn't finished loading yet so showing the window
  712. // now is ugly. We'll remember this put_visible was done, and
  713. // show the window when the UI panels have fully loaded.
  714. m_fDeferMakeVisible = TRUE;
  715. }
  716. }
  717. else
  718. {
  719. DoShowWindow(SW_HIDE);
  720. }
  721. hr = S_OK;
  722. }
  723. return hr;
  724. }
  725. STDMETHODIMP CMarsWindow::get_panels(IMarsPanelCollection **ppPanels)
  726. {
  727. HRESULT hr = E_INVALIDARG;
  728. if(API_IsValidWritePtr(ppPanels))
  729. {
  730. *ppPanels = NULL;
  731. if(VerifyNotPassive(&hr))
  732. {
  733. hr = GetPanels()->QueryInterface(IID_IMarsPanelCollection, (void **)ppPanels);
  734. }
  735. }
  736. return hr;
  737. }
  738. STDMETHODIMP CMarsWindow::get_places(IMarsPlaceCollection **ppPlaces)
  739. {
  740. HRESULT hr = E_INVALIDARG;
  741. if(API_IsValidWritePtr(ppPlaces))
  742. {
  743. *ppPlaces = NULL;
  744. if(VerifyNotPassive(&hr))
  745. {
  746. hr = GetPlaces()->QueryInterface(IID_IMarsPlaceCollection, (void **)ppPlaces);
  747. }
  748. }
  749. return hr;
  750. }
  751. STDMETHODIMP CMarsWindow::setWindowDimensions( /*[in]*/ long lX, /*[in]*/ long lY, /*[in]*/ long lW, /*[in]*/ long lH )
  752. {
  753. HRESULT hr = SCRIPT_ERROR;
  754. if(VerifyNotPassive( &hr ))
  755. {
  756. if(SetWindowPos(NULL, lX, lY, lW, lH, SWP_NOACTIVATE | SWP_NOZORDER))
  757. {
  758. hr = S_OK;
  759. }
  760. }
  761. return hr;
  762. }
  763. STDMETHODIMP CMarsWindow::close()
  764. {
  765. HRESULT hr = S_OK;
  766. if(VerifyNotPassive(&hr))
  767. {
  768. PostMessage(WM_CLOSE, 0, 0);
  769. }
  770. return hr;
  771. }
  772. STDMETHODIMP CMarsWindow::refreshLayout()
  773. {
  774. HRESULT hr = S_OK;
  775. if(VerifyNotPassive( &hr ))
  776. {
  777. CPanelCollection *panels = GetPanels();
  778. if(panels) panels->Layout();
  779. }
  780. return hr;
  781. }
  782. //------------------------------------------------------------------------------
  783. //------------------------------------------------------------------------------
  784. // IOleWindow
  785. STDMETHODIMP CMarsWindow::GetWindow(HWND *phwnd)
  786. {
  787. HRESULT hr = E_INVALIDARG;
  788. if(API_IsValidWritePtr(phwnd))
  789. {
  790. if(IsWindow())
  791. {
  792. *phwnd = m_hWnd;
  793. hr = S_OK;
  794. }
  795. else
  796. {
  797. *phwnd = NULL;
  798. hr = E_FAIL;
  799. }
  800. }
  801. return hr;
  802. }
  803. STDMETHODIMP CMarsWindow::ContextSensitiveHelp(BOOL fEnterMode)
  804. {
  805. return E_NOTIMPL;
  806. }
  807. // IOleInPlaceUIWindow
  808. STDMETHODIMP CMarsWindow::GetBorder(LPRECT lprectBorder)
  809. {
  810. ATLASSERT(lprectBorder);
  811. // We don't negotiate any toolbar space -- if they want screen real estate
  812. // they won't get it from us willingly.
  813. return INPLACE_E_NOTOOLSPACE;
  814. }
  815. STDMETHODIMP CMarsWindow::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
  816. {
  817. ATLASSERT(pborderwidths);
  818. // Look buddy, we told you before -- we ain't giving you any of our pixels.
  819. return INPLACE_E_NOTOOLSPACE;
  820. }
  821. STDMETHODIMP CMarsWindow::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
  822. {
  823. ATLASSERT(pborderwidths);
  824. // Pushy OLE object wouldn't ya say?
  825. return E_UNEXPECTED; // return E_BITEME;
  826. }
  827. STDMETHODIMP CMarsWindow::SetActiveObject(IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
  828. {
  829. // REVIEW: Maybe this is how a panel should let us know it's active. We currently track that in
  830. // the CPanelCollection via SetActivePanel().
  831. return S_OK;
  832. }
  833. // IOleInPlaceFrame
  834. STDMETHODIMP CMarsWindow::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  835. {
  836. // Menus? We don't need no steenkin' menus.
  837. ATLASSERT(hmenuShared &&
  838. API_IsValidWritePtr(lpMenuWidths) &&
  839. (0 == lpMenuWidths->width[0]) &&
  840. (0 == lpMenuWidths->width[2]) &&
  841. (0 == lpMenuWidths->width[4]));
  842. return E_NOTIMPL;
  843. }
  844. STDMETHODIMP CMarsWindow::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  845. {
  846. return E_NOTIMPL;
  847. }
  848. STDMETHODIMP CMarsWindow::RemoveMenus(HMENU hmenuShared)
  849. {
  850. return E_NOTIMPL;
  851. }
  852. STDMETHODIMP CMarsWindow::SetStatusText(LPCOLESTR pszStatusText)
  853. {
  854. ATLASSERT((NULL == pszStatusText) || (API_IsValidString(pszStatusText)));
  855. return S_OK;
  856. }
  857. STDMETHODIMP CMarsWindow::EnableModeless(BOOL fEnable)
  858. {
  859. FAIL_AFTER_PASSIVATE();
  860. m_fEnableModeless = BOOLIFY(fEnable);
  861. return GetPanels()->DoEnableModeless(fEnable);
  862. }
  863. STDMETHODIMP CMarsWindow::TranslateAccelerator(LPMSG lpmsg, WORD wID)
  864. {
  865. // REVIEW: Should we make keyboard routing go through here?
  866. return S_FALSE;
  867. }
  868. //==================================================================
  869. // Window message handlers
  870. //==================================================================
  871. LRESULT CMarsWindow::ForwardToMarsHost(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  872. {
  873. bHandled = FALSE;
  874. if(m_spMarsHost)
  875. {
  876. MSG msg;
  877. msg.hwnd = m_hWnd;
  878. msg.message = uMsg;
  879. msg.wParam = wParam;
  880. msg.lParam = lParam;
  881. if(SUCCEEDED(m_spMarsHost->PreTranslateMessage( &msg )))
  882. {
  883. bHandled = TRUE;
  884. }
  885. }
  886. return 0;
  887. }
  888. LRESULT CMarsWindow::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  889. {
  890. SetIcon(GetThreadParam()->hIcon);
  891. return TRUE;
  892. }
  893. LRESULT CMarsWindow::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  894. {
  895. CPanelCollection *panels = GetPanels(); if(!panels) return 0;
  896. switch(wParam)
  897. {
  898. case SIZE_MINIMIZED:
  899. if(!m_fLayoutLocked)
  900. {
  901. panels->lockLayout();
  902. m_fLayoutLocked = TRUE;
  903. }
  904. break;
  905. case SIZE_MAXIMIZED:
  906. case SIZE_RESTORED :
  907. if(m_fLayoutLocked)
  908. {
  909. panels->unlockLayout();
  910. m_fLayoutLocked = FALSE;
  911. }
  912. // Fall through...
  913. default:
  914. panels->Layout();
  915. break;
  916. }
  917. return 0;
  918. }
  919. LRESULT CMarsWindow::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  920. {
  921. if(GetThreadParam()->dwFlags & MTF_MANAGE_WINDOW_SIZE)
  922. {
  923. CGlobalSettingsRegKey regkey;
  924. if(InitWindowPosition( regkey, TRUE ))
  925. {
  926. SaveWindowPosition( regkey );
  927. }
  928. }
  929. Passivate();
  930. return FALSE;
  931. }
  932. LRESULT CMarsWindow::OnNCActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  933. {
  934. LRESULT lResult;
  935. if(!m_fShowTitleBar && !IsIconic())
  936. {
  937. lResult = TRUE;
  938. }
  939. else
  940. {
  941. lResult = DefWindowProc(uMsg, wParam, lParam);
  942. }
  943. return lResult;
  944. }
  945. LRESULT CMarsWindow::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  946. {
  947. WORD wActive = LOWORD(wParam);
  948. if(wActive == WA_INACTIVE)
  949. {
  950. //
  951. // If we are the active window, remember the focus location, to restore it later.
  952. //
  953. if(m_fActiveWindow)
  954. {
  955. if(!IsPassive()) m_hwndFocus = GetFocus();
  956. m_fActiveWindow = FALSE;
  957. }
  958. }
  959. else
  960. {
  961. m_fActiveWindow = TRUE;
  962. }
  963. bHandled = FALSE;
  964. return 0;
  965. }
  966. LRESULT CMarsWindow::OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  967. {
  968. MINMAXINFO *pInfo = (MINMAXINFO *)lParam;
  969. CPanelCollection *spPanels = GetPanels();
  970. if(spPanels)
  971. {
  972. long lAdjustWidth;
  973. long lAdjustHeight;
  974. POINT ptMin;
  975. POINT ptMax;
  976. RECT rcClient;
  977. RECT rcWindow;
  978. GetMinMaxInfo( spPanels, 0, ptMin, ptMax );
  979. GetClientRect( &rcClient );
  980. GetWindowRect( &rcWindow );
  981. lAdjustWidth = (rcWindow.right - rcWindow.left) - (rcClient.right - rcClient.left);
  982. lAdjustHeight = (rcWindow.bottom - rcWindow.top ) - (rcClient.bottom - rcClient.top );
  983. if(ptMin.x >= 0) pInfo->ptMinTrackSize.x = ptMin.x + lAdjustWidth ;
  984. if(ptMin.y >= 0) pInfo->ptMinTrackSize.y = ptMin.y + lAdjustHeight;
  985. if(ptMax.x >= 0) pInfo->ptMaxTrackSize.x = ptMax.x + lAdjustWidth ;
  986. if(ptMax.y >= 0) pInfo->ptMaxTrackSize.y = ptMax.y + lAdjustHeight;
  987. }
  988. return 0;
  989. }
  990. void CMarsWindow::GetMinMaxInfo( CPanelCollection *spPanels, int index, POINT& ptMin, POINT& ptMax )
  991. {
  992. ptMin.x = -1;
  993. ptMin.y = -1;
  994. ptMax.x = -1;
  995. ptMax.y = -1;
  996. if(spPanels && index < spPanels->GetSize())
  997. {
  998. CMarsPanel* pPanel = (*spPanels)[index++];
  999. if(pPanel)
  1000. {
  1001. PANEL_POSITION pos = pPanel->GetPosition();
  1002. if(pos != PANEL_POPUP)
  1003. {
  1004. if(pPanel->IsVisible())
  1005. {
  1006. POINT ptOurMin;
  1007. POINT ptOurMax;
  1008. POINT ptSubMin;
  1009. POINT ptSubMax;
  1010. pPanel->GetMinMaxInfo( ptOurMin, ptOurMax );
  1011. GetMinMaxInfo( spPanels, index, ptSubMin, ptSubMax );
  1012. if(pos == PANEL_BOTTOM || pos == PANEL_TOP)
  1013. {
  1014. selectMin( ptMin.x, ptOurMin.x, ptSubMin.x );
  1015. selectMax( ptMax.x, ptOurMax.x, ptSubMax.x );
  1016. }
  1017. else
  1018. {
  1019. combineMin( ptMin.x, ptOurMin.x, ptSubMin.x );
  1020. combineMax( ptMax.x, ptOurMax.x, ptSubMax.x );
  1021. }
  1022. if(pos == PANEL_LEFT || pos == PANEL_RIGHT)
  1023. {
  1024. selectMin( ptMin.y, ptOurMin.y, ptSubMin.y );
  1025. selectMax( ptMax.y, ptOurMax.y, ptSubMax.y );
  1026. }
  1027. else
  1028. {
  1029. combineMin( ptMin.y, ptOurMin.y, ptSubMin.y );
  1030. combineMax( ptMax.y, ptOurMax.y, ptSubMax.y );
  1031. }
  1032. }
  1033. else
  1034. {
  1035. GetMinMaxInfo( spPanels, index, ptMin, ptMax );
  1036. }
  1037. }
  1038. }
  1039. }
  1040. }
  1041. bool CMarsWindow::CanLayout( /*[in/out]*/ RECT rcClient )
  1042. {
  1043. CPanelCollection *spPanels = GetPanels();
  1044. if(spPanels)
  1045. {
  1046. for(int i=0; i<spPanels->GetSize(); i++)
  1047. {
  1048. CMarsPanel* pPanel = (*spPanels)[i];
  1049. POINT ptDiff;
  1050. if(pPanel->CanLayout( rcClient, ptDiff ) == false)
  1051. {
  1052. return false;
  1053. }
  1054. }
  1055. }
  1056. return true;
  1057. }
  1058. void CMarsWindow::FixLayout( /*[in/out]*/ RECT rcClient )
  1059. {
  1060. CPanelCollection *spPanels = GetPanels();
  1061. if(spPanels)
  1062. {
  1063. POINT ptDiff;
  1064. FixLayout( spPanels, 0, rcClient, ptDiff );
  1065. }
  1066. }
  1067. void CMarsWindow::FixLayout( CPanelCollection *spPanels, int index, RECT rcClient, POINT& ptDiff )
  1068. {
  1069. ptDiff.x = 0;
  1070. ptDiff.y = 0;
  1071. if(index < spPanels->GetSize())
  1072. {
  1073. CMarsPanel* pPanel = (*spPanels)[index++];
  1074. PANEL_POSITION pos = pPanel->GetPosition();
  1075. RECT rcClient2 = rcClient;
  1076. POINT ptSubDiff;
  1077. //
  1078. // First round, try to fix first ourselves and then lets the other fix themselves.
  1079. //
  1080. if(pPanel->CanLayout( rcClient2, ptDiff ) == false)
  1081. {
  1082. if(pos == PANEL_BOTTOM || pos == PANEL_TOP)
  1083. {
  1084. if(ptDiff.y)
  1085. {
  1086. pPanel->put_height( pPanel->GetHeight() - ptDiff.y );
  1087. }
  1088. }
  1089. if(pos == PANEL_LEFT || pos == PANEL_RIGHT)
  1090. {
  1091. if(ptDiff.x)
  1092. {
  1093. pPanel->put_width ( pPanel->GetWidth () - ptDiff.x );
  1094. }
  1095. }
  1096. rcClient2 = rcClient;
  1097. pPanel->CanLayout( rcClient2, ptDiff );
  1098. }
  1099. FixLayout( spPanels, index, rcClient2, ptSubDiff );
  1100. //
  1101. // Second round, based on what the other panels need, we adjust.
  1102. //
  1103. if(pos == PANEL_BOTTOM || pos == PANEL_TOP)
  1104. {
  1105. if(ptSubDiff.y)
  1106. {
  1107. pPanel->put_height( pPanel->GetHeight() - ptSubDiff.y );
  1108. }
  1109. }
  1110. if(pos == PANEL_LEFT || pos == PANEL_RIGHT)
  1111. {
  1112. if(ptSubDiff.x)
  1113. {
  1114. pPanel->put_width ( pPanel->GetWidth () - ptSubDiff.x );
  1115. }
  1116. }
  1117. pPanel->CanLayout( rcClient, ptDiff );
  1118. FixLayout( spPanels, index, rcClient2, ptSubDiff );
  1119. ptDiff.x += ptSubDiff.x;
  1120. ptDiff.y += ptSubDiff.y;
  1121. }
  1122. }
  1123. void DrawFrame(HDC hdc, LPRECT prc, HBRUSH hbrColor, int cl)
  1124. {
  1125. HBRUSH hbr;
  1126. int cx, cy;
  1127. RECT rcT;
  1128. ATLASSERT(NULL != prc);
  1129. int cyBorder = GetSystemMetrics(SM_CYBORDER);
  1130. int cxBorder = GetSystemMetrics(SM_CXBORDER);
  1131. rcT = *prc;
  1132. cx = cl * cxBorder;
  1133. cy = cl * cyBorder;
  1134. hbr = (HBRUSH)SelectObject(hdc, hbrColor);
  1135. PatBlt(hdc, rcT.left, rcT.top, cx, rcT.bottom - rcT.top, PATCOPY);
  1136. rcT.left += cx;
  1137. PatBlt(hdc, rcT.left, rcT.top, rcT.right - rcT.left, cy, PATCOPY);
  1138. rcT.top += cy;
  1139. rcT.right -= cx;
  1140. PatBlt(hdc, rcT.right, rcT.top, cx, rcT.bottom - rcT.top, PATCOPY);
  1141. rcT.bottom -= cy;
  1142. PatBlt(hdc, rcT.left, rcT.bottom, rcT.right - rcT.left, cy, PATCOPY);
  1143. SelectObject(hdc, hbr);
  1144. *prc = rcT;
  1145. }
  1146. // For now it looks like we can let windows handle this since we are adjusting
  1147. // the client rect ourselves in OnNCCalcSize.
  1148. LRESULT CMarsWindow::OnNCPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1149. {
  1150. LRESULT lResult;
  1151. if(!m_fShowTitleBar)
  1152. {
  1153. HDC hdc = GetDCEx(wParam != 1 ? (HRGN)wParam : NULL, DCX_WINDOW | DCX_INTERSECTRGN);
  1154. if(NULL == hdc)
  1155. {
  1156. hdc = GetWindowDC();
  1157. }
  1158. RECT rcWindow;
  1159. GetWindowRect(&rcWindow);
  1160. OffsetRect(&rcWindow, -rcWindow.left, -rcWindow.top);
  1161. HBRUSH hbrBorder = CreateSolidBrush(GetSysColor(COLOR_ACTIVEBORDER));
  1162. HBRUSH hbrFrame = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
  1163. DrawEdge(hdc, &rcWindow, EDGE_RAISED, (BF_RECT | BF_ADJUST));
  1164. NONCLIENTMETRICSA ncm;
  1165. ncm.cbSize = sizeof(ncm);
  1166. SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(ncm), (void *)(LPNONCLIENTMETRICS)&ncm, 0);
  1167. DrawFrame(hdc, &rcWindow, hbrBorder, ncm.iBorderWidth);
  1168. DrawFrame(hdc, &rcWindow, hbrFrame, 1);
  1169. DeleteObject(hbrBorder);
  1170. DeleteObject(hbrFrame);
  1171. ReleaseDC(hdc);
  1172. lResult = 0;
  1173. }
  1174. else
  1175. {
  1176. lResult = DefWindowProc(uMsg, wParam, lParam);
  1177. }
  1178. return lResult;
  1179. }
  1180. LRESULT CMarsWindow::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1181. {
  1182. PAINTSTRUCT ps;
  1183. BeginPaint(&ps);
  1184. EndPaint(&ps);
  1185. return 0;
  1186. }
  1187. LRESULT CMarsWindow::OnPaletteChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1188. {
  1189. HWND hwndPaletteChange = (HWND)wParam;
  1190. // Ignore if we changed the palette
  1191. if(hwndPaletteChange == m_hWnd)
  1192. return 0;
  1193. // If we are the active window and one of our children set the forground palette
  1194. // we want to avoid realizing our palette in the foreground or we get in a tug-of-war
  1195. // with lots of flashing.
  1196. if(IsChild(hwndPaletteChange) && (m_hWnd == GetForegroundWindow()))
  1197. {
  1198. // Our child caused a palette change so force a redraw to use the
  1199. // new system palette. Children shouldn't do this, bad child!
  1200. RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
  1201. }
  1202. else
  1203. {
  1204. // Select our foreground palette
  1205. OnQueryNewPalette(uMsg, wParam, lParam, bHandled);
  1206. }
  1207. return 0;
  1208. }
  1209. LRESULT CMarsWindow::OnQueryNewPalette(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1210. {
  1211. LRESULT lResult = FALSE;
  1212. // Realize our palette
  1213. if(g_hpalHalftone)
  1214. {
  1215. HDC hDC = GetDC();
  1216. if(hDC)
  1217. {
  1218. if(GetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE)
  1219. {
  1220. HPALETTE hOldPal = SelectPalette(hDC, g_hpalHalftone, FALSE);
  1221. UINT i = RealizePalette(hDC);
  1222. // Did the realization change? (We need to always invalidate background windows
  1223. // because when we have multiple windows up only the first top-level
  1224. // window will actually realize any colors. Windows lower in the
  1225. // z-order always get 0 returned from RealizePalette, but they
  1226. // may need repainting! We could further optimize by having the top
  1227. // html window invalidate all the rest when i is non-zero. -- StevePro)
  1228. if(i || (m_hWnd != GetForegroundWindow()))
  1229. {
  1230. // Yes, so force a repaint.
  1231. RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
  1232. }
  1233. SelectPalette(hDC, hOldPal, TRUE);
  1234. RealizePalette(hDC);
  1235. // lResult = i;
  1236. lResult = TRUE;
  1237. }
  1238. ReleaseDC(hDC);
  1239. }
  1240. }
  1241. return lResult;
  1242. }
  1243. LRESULT CMarsWindow::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1244. {
  1245. // We need to update our palette because some of the "reserved" colors may have changed
  1246. HPALETTE hpal = SHCreateShellPalette(NULL);
  1247. hpal = (HPALETTE)InterlockedExchangePointer( (LPVOID*)&g_hpalHalftone, hpal);
  1248. if(hpal)
  1249. {
  1250. DeleteObject(hpal);
  1251. }
  1252. PostMessage(WM_QUERYNEWPALETTE, 0, (LPARAM) -1);
  1253. // Trident likes to know about these changes
  1254. ForwardMessageToChildren(uMsg, wParam, lParam);
  1255. bHandled = FALSE;
  1256. return 0;
  1257. }
  1258. LRESULT CMarsWindow::OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1259. {
  1260. return OnSysColorChange(uMsg, wParam, lParam, bHandled);
  1261. }
  1262. LRESULT CMarsWindow::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1263. {
  1264. if(wParam == SC_MINIMIZE)
  1265. {
  1266. //
  1267. // If we are the active window, remember the focus location, to restore it later.
  1268. //
  1269. if(m_fActiveWindow)
  1270. {
  1271. if(!IsPassive()) m_hwndFocus = GetFocus();
  1272. m_fActiveWindow = FALSE;
  1273. }
  1274. }
  1275. bHandled = FALSE;
  1276. return 0;
  1277. }
  1278. LRESULT CMarsWindow::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1279. {
  1280. //
  1281. // If we have a saved focus location, restore it.
  1282. //
  1283. if(m_hwndFocus && m_hwndFocus != m_hWnd)
  1284. {
  1285. ::SetFocus( m_hwndFocus );
  1286. }
  1287. return 0;
  1288. }
  1289. LRESULT CMarsWindow::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1290. {
  1291. return TRUE;
  1292. }
  1293. LRESULT CMarsWindow::OnNCCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1294. {
  1295. LRESULT lResult;
  1296. if(!m_fShowTitleBar && !IsIconic())
  1297. {
  1298. RECT *prc = (RECT *)lParam;
  1299. NONCLIENTMETRICSA ncm;
  1300. ncm.cbSize = sizeof(ncm);
  1301. SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE);
  1302. int xDelta = GetSystemMetrics(SM_CXEDGE) + ncm.iBorderWidth + 1;
  1303. int yDelta = GetSystemMetrics(SM_CYEDGE) + ncm.iBorderWidth + 1;
  1304. InflateRect(prc, -xDelta, -yDelta);
  1305. lResult = 0;
  1306. }
  1307. else
  1308. {
  1309. lResult = DefWindowProc(uMsg, wParam, lParam);
  1310. }
  1311. return lResult;
  1312. }
  1313. LRESULT CMarsWindow::OnSetText(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1314. {
  1315. // HACK 'O RAMA: Turn off one of the WS_CAPTION style bits (WS_CAPTION == WS_BORDER | WS_DLGFRAME)
  1316. // so that USER32 doesn't try and draw the title bar for us.
  1317. DWORD dwStyle = GetWindowLong(GWL_STYLE);
  1318. SetWindowLong(GWL_STYLE, dwStyle & ~WS_DLGFRAME);
  1319. LRESULT lResult = DefWindowProc();
  1320. SetWindowLong(GWL_STYLE, dwStyle);
  1321. return lResult;
  1322. }
  1323. void CMarsWindow::OnFinalMessage(HWND hWnd)
  1324. {
  1325. PostQuitMessage(0);
  1326. }
  1327. //==================================================================
  1328. // Panel/Place methods
  1329. //==================================================================
  1330. void CMarsWindow::DoShowWindow(int nCmdShow)
  1331. {
  1332. if(GetThreadParam()->dwFlags & MTF_DONT_SHOW_WINDOW) return;
  1333. ShowWindow( nCmdShow );
  1334. // Win95 doesn't let the window from another thread appear in front of an
  1335. // existing window, so we must grab the foreground
  1336. if(IsWindowVisible())
  1337. {
  1338. SetForegroundWindow(m_hWnd);
  1339. }
  1340. }
  1341. void CMarsWindow::OnTransitionComplete()
  1342. {
  1343. if(!m_fUIPanelsReady && !IsWindowVisible())
  1344. {
  1345. m_fUIPanelsReady = TRUE;
  1346. // start with the Mars window host's requested show mode
  1347. int nCmdShow = GetThreadParam()->nCmdShow;
  1348. if((nCmdShow == SW_HIDE) && m_fDeferMakeVisible)
  1349. {
  1350. // nCmdShow is SW_HIDE to indicate that the window should be shown
  1351. // via put_visible. In this case, someone did a pub_visible(TRUE) before
  1352. // our UI panels were finished loading, so we'll honor the request now.
  1353. nCmdShow = SW_SHOW;
  1354. }
  1355. // only promote to maximized state if we are going to become visible
  1356. if((nCmdShow != SW_HIDE) && m_fStartMaximized)
  1357. {
  1358. nCmdShow = SW_MAXIMIZE;
  1359. }
  1360. DoShowWindow(nCmdShow);
  1361. }
  1362. }
  1363. HRESULT CMarsWindow::ReleaseOwnedObjects(IUnknown *pUnknownOwner)
  1364. {
  1365. return S_OK;
  1366. }
  1367. void CMarsWindow::SetFirstPlace( LPCWSTR szPlace )
  1368. {
  1369. if(!m_bstrFirstPlace)
  1370. {
  1371. m_bstrFirstPlace = szPlace;
  1372. }
  1373. }
  1374. void CMarsWindow::ShowTitleBar(BOOL fShowTitleBar)
  1375. {
  1376. if(!!m_fShowTitleBar != !!fShowTitleBar)
  1377. {
  1378. m_fShowTitleBar = fShowTitleBar ? TRUE : FALSE;
  1379. SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE | SWP_FRAMECHANGED);
  1380. }
  1381. }
  1382. BOOL CMarsWindow::TranslateAccelerator(MSG &msg)
  1383. {
  1384. BOOL bProcessed = FALSE;
  1385. // if(msg.message == WM_SYSKEYDOWN)
  1386. // {
  1387. // switch (msg.wParam)
  1388. // {
  1389. // case VK_LEFT:
  1390. // case VK_RIGHT:
  1391. // GetTravelLog()->travel((msg.wParam == VK_LEFT) ? -1 : 1);
  1392. // bProcessed = TRUE;
  1393. // break;
  1394. // }
  1395. // }
  1396. return bProcessed;
  1397. }
  1398. BOOL CMarsWindow::PreTranslateMessage(MSG &msg)
  1399. {
  1400. // Set to TRUE if you don't want this message dispatched normally
  1401. BOOL bProcessed = FALSE;
  1402. switch (msg.message)
  1403. {
  1404. case WM_SETFOCUS:
  1405. break;
  1406. default:
  1407. if((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST))
  1408. {
  1409. // First we take a crack
  1410. bProcessed = TranslateAccelerator(msg);
  1411. // Now let the active place try
  1412. if(!bProcessed)
  1413. {
  1414. CMarsPlace *pPlace = GetPlaces()->GetCurrentPlace();
  1415. if(NULL != pPlace)
  1416. {
  1417. bProcessed = (pPlace->TranslateAccelerator(&msg) == S_OK);
  1418. }
  1419. }
  1420. }
  1421. else if((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
  1422. {
  1423. if(m_bSingleButtonMouse)
  1424. {
  1425. switch (msg.message)
  1426. {
  1427. case WM_RBUTTONDOWN:
  1428. case WM_MBUTTONDOWN:
  1429. msg.message = WM_LBUTTONDOWN;
  1430. break;
  1431. case WM_RBUTTONUP:
  1432. case WM_MBUTTONUP:
  1433. msg.message = WM_LBUTTONUP;
  1434. break;
  1435. case WM_RBUTTONDBLCLK:
  1436. case WM_MBUTTONDBLCLK:
  1437. msg.message = WM_LBUTTONDBLCLK;
  1438. break;
  1439. }
  1440. }
  1441. }
  1442. }
  1443. return bProcessed;
  1444. }
  1445. bool CMarsWindow::InitWindowPosition( CGlobalSettingsRegKey& regkey, BOOL fWrite )
  1446. {
  1447. WCHAR rgPath[MAX_PATH];
  1448. RECT rc;
  1449. if(::GetClientRect( ::GetDesktopWindow(), &rc ))
  1450. {
  1451. LPCWSTR szTitle = GetThreadParam()->pwszTitle; if(!szTitle) szTitle = L"<DEFAULT>";
  1452. LONG Screen_width = rc.right - rc.left;
  1453. LONG Screen_height = rc.bottom - rc.top;
  1454. StringCchPrintfW( rgPath, ARRAYSIZE(rgPath), WZ_WINDOWPLACEMENT, (int)Screen_width, (int)Screen_height, szTitle );
  1455. if(fWrite)
  1456. {
  1457. if(regkey.CreateGlobalSubkey( rgPath ) == ERROR_SUCCESS) return true;
  1458. }
  1459. else
  1460. {
  1461. if(regkey.OpenGlobalSubkey( rgPath ) == ERROR_SUCCESS) return true;
  1462. }
  1463. }
  1464. return false;
  1465. }
  1466. void CMarsWindow::SaveWindowPosition( CGlobalSettingsRegKey& regkey )
  1467. {
  1468. WINDOWPLACEMENT wp; wp.length = sizeof(wp);
  1469. GetWindowPlacement( &wp );
  1470. WriteWindowPosition(regkey, &wp.rcNormalPosition, IsZoomed());
  1471. }
  1472. void CMarsWindow::LoadWindowPosition( CGlobalSettingsRegKey& regkey, BOOL fAllowMaximized, WINDOWPLACEMENT& wp, BOOL& fMaximized )
  1473. {
  1474. RECT rc;
  1475. // Use default values if there is no valid registry data
  1476. if(ERROR_SUCCESS != regkey.QueryBoolValue(fMaximized, WZ_POSITIONMAX))
  1477. {
  1478. fMaximized = fAllowMaximized;
  1479. }
  1480. if(ERROR_SUCCESS != regkey.QueryBinaryValue(&rc, sizeof(rc), WZ_POSITIONRECT))
  1481. {
  1482. rc = wp.rcNormalPosition;
  1483. GetThreadParam()->dwFlags &= ~MTF_RESTORING_FROM_REGISTRY;
  1484. }
  1485. else
  1486. {
  1487. GetThreadParam()->dwFlags |= MTF_RESTORING_FROM_REGISTRY;
  1488. }
  1489. // If the window is about to open with the same top-left corner as another
  1490. // Mars window, cascade it.
  1491. if(IsWindowOverlayed( m_hWnd, rc.left, rc.top ))
  1492. {
  1493. CascadeWindowRectOnMonitor( m_hWnd, &rc );
  1494. }
  1495. // Always make sure the window is fully on-screen
  1496. BoundWindowRectToMonitor( m_hWnd, &rc );
  1497. // Don't use maximized setting if we're opened by script
  1498. m_fStartMaximized = fMaximized && fAllowMaximized;
  1499. // Now set the size of the window -- we should be hidden at this point
  1500. wp.rcNormalPosition = rc;
  1501. wp.showCmd = IsWindowVisible() ? (fMaximized ? SW_MAXIMIZE : SW_NORMAL) : SW_HIDE;
  1502. }
  1503. void CMarsWindow::SpinMessageLoop( BOOL fWait )
  1504. {
  1505. MSG msg;
  1506. while(fWait ? GetMessage( &msg, NULL, 0, 0 ) : PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
  1507. {
  1508. if(m_spMarsHost && SUCCEEDED(m_spMarsHost->PreTranslateMessage( &msg ))) continue;
  1509. if(!PreTranslateMessage( msg ))
  1510. {
  1511. TranslateMessage( &msg );
  1512. DispatchMessage ( &msg );
  1513. }
  1514. if(IsPassive()) break;
  1515. }
  1516. }
  1517. //==================================================================
  1518. // Mars App
  1519. //==================================================================
  1520. HRESULT STDMETHODCALLTYPE MarsThreadProc(IMarsHost *pMarsHost, MARSTHREADPARAM *pThreadParam)
  1521. {
  1522. HRESULT hr;
  1523. if (!CThreadData::HaveData() && (NULL != pThreadParam) &&
  1524. (pThreadParam->cbSize == sizeof(*pThreadParam)))
  1525. {
  1526. hr = E_OUTOFMEMORY;
  1527. CThreadData *pThreadData = new CThreadData;
  1528. if (pThreadData && CThreadData::TlsSetValue(pThreadData))
  1529. {
  1530. hr = CoInitialize(NULL);
  1531. if(SUCCEEDED(hr))
  1532. {
  1533. MarsAxWinInit();
  1534. CComClassPtr<CMarsWindow> spMarsWindow;
  1535. CMarsWindow::CreateInstance(pMarsHost, pThreadParam, &spMarsWindow);
  1536. if(spMarsWindow)
  1537. {
  1538. spMarsWindow->SpinMessageLoop( TRUE );
  1539. // Ensure that no matter what the window is passivated & then release it
  1540. if (!spMarsWindow->IsPassive())
  1541. {
  1542. spMarsWindow->Passivate();
  1543. }
  1544. }
  1545. CoUninitialize();
  1546. }
  1547. CThreadData::TlsSetValue(NULL); // paranoia
  1548. }
  1549. delete pThreadData;
  1550. }
  1551. else
  1552. {
  1553. if(pThreadParam)
  1554. {
  1555. ATLASSERT(pThreadParam->cbSize == sizeof(*pThreadParam));
  1556. }
  1557. // If we already have TLS data then we are being reentered -- this is not a good thing!
  1558. hr = E_UNEXPECTED;
  1559. }
  1560. return hr;
  1561. }