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.

732 lines
22 KiB

  1. //=--------------------------------------------------------------------------=
  2. // CtlView.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995-1996 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // implementation of the IViewObjectEx interface, which is a moderately
  13. // non-trivial bunch of code.
  14. //
  15. #include "IPServer.H"
  16. #include "CtrlObj.H"
  17. #include "Globals.H"
  18. #include "Util.H"
  19. // for ASSERT and FAIL
  20. //
  21. SZTHISFILE
  22. // local functions we're going to find useful
  23. //
  24. HDC _CreateOleDC(DVTARGETDEVICE *ptd);
  25. //=--------------------------------------------------------------------------=
  26. // COleControl::Draw [IViewObject2]
  27. //=--------------------------------------------------------------------------=
  28. // Draws a representation of an object onto the specified device context.
  29. //
  30. // Parameters:
  31. // DWORD - [in] draw aspect
  32. // LONG - [in] part of object to draw [not relevant]
  33. // void * - NULL
  34. // DVTARGETDEVICE * - [in] specifies the target device
  35. // HDC - [in] information context for target device
  36. // HDC - [in] target device context
  37. // LPCRECTL - [in] rectangle in which the object is drawn
  38. // LPCRECTL - [in] window extent and origin for metafiles
  39. // BOOL (*)(DWORD) - [in] callback for continuing or cancelling drawing
  40. // DWORD - [in] parameter to pass to callback.
  41. //
  42. // Output:
  43. // HRESULT
  44. //
  45. // Notes:
  46. // - we support the following OCX 96 extensions
  47. // a. flicker free drawing [multi-pass drawing]
  48. // b. pvAspect != NULL for optimized DC handling
  49. // c. prcBounds == NULL for windowless inplace active objects
  50. //
  51. STDMETHODIMP COleControl::Draw
  52. (
  53. DWORD dwDrawAspect,
  54. LONG lIndex,
  55. void *pvAspect,
  56. DVTARGETDEVICE *ptd,
  57. HDC hicTargetDevice,
  58. HDC hdcDraw,
  59. LPCRECTL prcBounds,
  60. LPCRECTL prcWBounds,
  61. BOOL (__stdcall *pfnContinue)(ULONG_PTR dwContinue),
  62. ULONG_PTR dwContinue
  63. )
  64. {
  65. HRESULT hr;
  66. RECTL rc;
  67. POINT pVp, pW;
  68. BOOL fOptimize = FALSE;
  69. int iMode;
  70. BYTE fMetafile = FALSE;
  71. BYTE fDeleteDC = FALSE;
  72. // support the aspects required for multi-pass drawing
  73. //
  74. switch (dwDrawAspect) {
  75. case DVASPECT_CONTENT:
  76. case DVASPECT_OPAQUE:
  77. case DVASPECT_TRANSPARENT:
  78. break;
  79. default:
  80. return DV_E_DVASPECT;
  81. }
  82. // first, have to do a little bit to support printing.
  83. //
  84. if (GetDeviceCaps(hdcDraw, TECHNOLOGY) == DT_METAFILE) {
  85. // We are dealing with a metafile.
  86. //
  87. fMetafile = TRUE;
  88. // If attributes DC is NULL, create one, based on ptd.
  89. //
  90. if (!hicTargetDevice) {
  91. // Does _CreateOleDC have to return an hDC
  92. // or can it be flagged to return an hIC
  93. // for this particular case?
  94. //
  95. hicTargetDevice = _CreateOleDC(ptd);
  96. fDeleteDC = TRUE;
  97. }
  98. }
  99. // check to see if we have any flags passed in the pvAspect parameter.
  100. //
  101. if (pvAspect && ((DVASPECTINFO *)pvAspect)->cb == sizeof(DVASPECTINFO))
  102. fOptimize = (((DVASPECTINFO *)pvAspect)->dwFlags & DVASPECTINFOFLAG_CANOPTIMIZE) ? TRUE : FALSE;
  103. // if we are windowless, then we just pass this on to the end control code.
  104. //
  105. if (m_fInPlaceActive) {
  106. // give them a rectangle with which to draw
  107. //
  108. //ASSERT(!m_fInPlaceActive || !prcBounds, "Inplace active and somebody passed in prcBounds!!!");
  109. if (prcBounds)
  110. memcpy(&rc, prcBounds, sizeof(rc));
  111. else
  112. memcpy(&rc, &m_rcLocation, sizeof(rc));
  113. } else {
  114. // first -- convert the DC back to MM_TEXT mapping mode so that the
  115. // window proc and OnDraw can share the same painting code. save
  116. // some information on it, so we can restore it later [without using
  117. // a SaveDC/RestoreDC]
  118. //
  119. rc = *prcBounds;
  120. // Don't do anything to hdcDraw if it's a metafile.
  121. // The control's Draw method must make the appropriate
  122. // accomodations for drawing to a metafile
  123. //
  124. if (!fMetafile) {
  125. LPtoDP(hdcDraw, (POINT *)&rc, 2);
  126. SetViewportOrgEx(hdcDraw, 0, 0, &pVp);
  127. SetWindowOrgEx(hdcDraw, 0, 0, &pW);
  128. iMode = SetMapMode(hdcDraw, MM_TEXT);
  129. }
  130. }
  131. // prcWBounds is NULL and not used if we are not dealing with a metafile.
  132. // For metafiles, we pass on rc as *prcBounds, we should also include
  133. // prcWBounds
  134. //
  135. hr = OnDraw(dwDrawAspect, hdcDraw, &rc, prcWBounds, hicTargetDevice, fOptimize);
  136. // clean up the DC when we're done with it, if appropriate.
  137. //
  138. if (!m_fInPlaceActive) {
  139. SetViewportOrgEx(hdcDraw, pVp.x, pVp.y, NULL);
  140. SetWindowOrgEx(hdcDraw, pW.x, pW.y, NULL);
  141. SetMapMode(hdcDraw, iMode);
  142. }
  143. // if we created a dc, blow it away now
  144. //
  145. if (fDeleteDC) DeleteDC(hicTargetDevice);
  146. return hr;
  147. }
  148. //=--------------------------------------------------------------------------=
  149. // COleControl::DoSuperClassPaint
  150. //=--------------------------------------------------------------------------=
  151. // design time painting of a subclassed control.
  152. //
  153. // Parameters:
  154. // HDC - [in] dc to work with
  155. // LPCRECTL - [in] rectangle to paint to. should be in pixels
  156. //
  157. // Output:
  158. // HRESULT
  159. //
  160. // Notes:
  161. //
  162. HRESULT COleControl::DoSuperClassPaint
  163. (
  164. HDC hdc,
  165. LPCRECTL prcBounds
  166. )
  167. {
  168. HWND hwnd;
  169. RECT rcClient;
  170. int iMapMode;
  171. POINT ptWOrg, ptVOrg;
  172. SIZE sWOrg, sVOrg;
  173. // make sure we have a window.
  174. //
  175. hwnd = CreateInPlaceWindow(0,0, FALSE);
  176. if (!hwnd)
  177. return E_FAIL;
  178. GetClientRect(hwnd, &rcClient);
  179. // set up the DC for painting. this code largely taken from the MFC CDK
  180. // DoSuperClassPaint() fn. doesn't always get things like command
  181. // buttons quite right ...
  182. //
  183. // NOTE: there is a windows 95 problem in which the font instance manager
  184. // will leak a bunch of bytes in the global GDI pool whenever you
  185. // change your extents and have an active font. this code gets around
  186. // this for on-screen cases, but not for printing [which shouldn't be
  187. // too serious, because you're not often changing your control size and
  188. // printing rapidly in succession]
  189. //
  190. if ((rcClient.right - rcClient.left != prcBounds->right - prcBounds->left)
  191. && (rcClient.bottom - rcClient.top != prcBounds->bottom - prcBounds->top)) {
  192. iMapMode = SetMapMode(hdc, MM_ANISOTROPIC);
  193. SetWindowExtEx(hdc, rcClient.right, rcClient.bottom, &sWOrg);
  194. SetViewportExtEx(hdc, prcBounds->right - prcBounds->left, prcBounds->bottom - prcBounds->top, &sVOrg);
  195. }
  196. SetWindowOrgEx(hdc, 0, 0, &ptWOrg);
  197. SetViewportOrgEx(hdc, prcBounds->left, prcBounds->top, &ptVOrg);
  198. #if STRICT
  199. CallWindowProc((WNDPROC)SUBCLASSWNDPROCOFCONTROL(m_ObjectType), hwnd, (g_fSysWin95Shell) ? WM_PRINT : WM_PAINT, (WPARAM)hdc, (LPARAM)(g_fSysWin95Shell ? PRF_CHILDREN | PRF_CLIENT : 0));
  200. #else
  201. CallWindowProc((FARPROC)SUBCLASSWNDPROCOFCONTROL(m_ObjectType), hwnd, (g_fSysWin95Shell) ? WM_PRINT : WM_PAINT, (WPARAM)hdc, (LPARAM)(g_fSysWin95Shell ? PRF_CHILDREN | PRF_CLIENT : 0));
  202. #endif // STRICT
  203. return S_OK;
  204. }
  205. //=--------------------------------------------------------------------------=
  206. // COleControl::GetColorSet [IViewObject2]
  207. //=--------------------------------------------------------------------------=
  208. // Returns the logical palette that the control will use for drawing in its
  209. // IViewObject::Draw method with the corresponding parameters.
  210. //
  211. // Parameters:
  212. // DWORD - [in] how the object is to be represented
  213. // LONG - [in] part of the object to draw [not relevant]
  214. // void * - NULL
  215. // DVTARGETDEVICE * - [in] specifies the target device
  216. // HDC - [in] information context for the target device
  217. // LOGPALETTE ** - [out] where to put palette
  218. //
  219. // Output:
  220. // S_OK - Control has a palette, and returned it through the out param.
  221. // S_FALSE - Control does not currently have a palette.
  222. // E_NOTIMPL - Control will never have a palette so optimize handling of this control.
  223. //
  224. // Notes:
  225. //
  226. STDMETHODIMP COleControl::GetColorSet
  227. (
  228. DWORD dwDrawAspect,
  229. LONG lindex,
  230. void *IgnoreMe,
  231. DVTARGETDEVICE *ptd,
  232. HDC hicTargetDevice,
  233. LOGPALETTE **ppColorSet
  234. )
  235. {
  236. if (dwDrawAspect != DVASPECT_CONTENT)
  237. return DV_E_DVASPECT;
  238. *ppColorSet = NULL;
  239. return (OnGetPalette(hicTargetDevice, ppColorSet)) ? ((*ppColorSet) ? S_OK : S_FALSE) : E_NOTIMPL;
  240. }
  241. //=--------------------------------------------------------------------------=
  242. // COleControl::Freeze [IViewObject2]
  243. //=--------------------------------------------------------------------------=
  244. // Freezes a certain aspect of the object's presentation so that it does not
  245. // change until the IViewObject::Unfreeze method is called.
  246. //
  247. // Parameters:
  248. // DWORD - [in] aspect
  249. // LONG - [in] part of object to draw
  250. // void * - NULL
  251. // DWORD * - [out] for Unfreeze
  252. //
  253. // Output:
  254. // HRESULT
  255. //
  256. // Notes:
  257. //
  258. STDMETHODIMP COleControl::Freeze
  259. (
  260. DWORD dwDrawAspect,
  261. LONG lIndex,
  262. void *IgnoreMe,
  263. DWORD *pdwFreeze
  264. )
  265. {
  266. return E_NOTIMPL;
  267. }
  268. //=--------------------------------------------------------------------------=
  269. // COleControl::Unfreeze [IVewObject2]
  270. //=--------------------------------------------------------------------------=
  271. // Releases a previously frozen drawing. The most common use of this method
  272. // is for banded printing.
  273. //
  274. // Parameters:
  275. // DWORD - [in] cookie from freeze
  276. //
  277. // Output:
  278. // HRESULT
  279. //
  280. // Notes:
  281. //
  282. STDMETHODIMP COleControl::Unfreeze
  283. (
  284. DWORD dwFreeze
  285. )
  286. {
  287. return E_NOTIMPL;
  288. }
  289. //=--------------------------------------------------------------------------=
  290. // COleControl::SetAdvise [IViewObject2]
  291. //=--------------------------------------------------------------------------=
  292. // Sets up a connection between the control and an advise sink so that the
  293. // advise sink can be notified about changes in the control's view.
  294. //
  295. // Parameters:
  296. // DWORD - [in] aspect
  297. // DWORD - [in] info about the sink
  298. // IAdviseSink * - [in] the sink
  299. //
  300. // Output:
  301. // HRESULT
  302. //
  303. // Notes:
  304. //
  305. STDMETHODIMP COleControl::SetAdvise
  306. (
  307. DWORD dwAspects,
  308. DWORD dwAdviseFlags,
  309. IAdviseSink *pAdviseSink
  310. )
  311. {
  312. // if it's not a content aspect, we don't support it.
  313. //
  314. if (!(dwAspects & DVASPECT_CONTENT)) {
  315. return DV_E_DVASPECT;
  316. }
  317. // set up some flags [we gotta stash for GetAdvise ...]
  318. //
  319. m_fViewAdvisePrimeFirst = (dwAdviseFlags & ADVF_PRIMEFIRST) ? TRUE : FALSE;
  320. m_fViewAdviseOnlyOnce = (dwAdviseFlags & ADVF_ONLYONCE) ? TRUE : FALSE;
  321. RELEASE_OBJECT(m_pViewAdviseSink);
  322. m_pViewAdviseSink = pAdviseSink;
  323. ADDREF_OBJECT(m_pViewAdviseSink);
  324. // prime them if they want it [we need to store this so they can get flags later]
  325. //
  326. if (m_fViewAdvisePrimeFirst)
  327. ViewChanged();
  328. return S_OK;
  329. }
  330. //=--------------------------------------------------------------------------=
  331. // COleControl::GetAdvise [IViewObject2]
  332. //=--------------------------------------------------------------------------=
  333. // Retrieves the existing advisory connection on the control if there is one.
  334. // This method simply returns the parameters used in the most recent call to
  335. // the IViewObject::SetAdvise method.
  336. //
  337. // Parameters:
  338. // DWORD * - [out] aspects
  339. // DWORD * - [out] advise flags
  340. // IAdviseSink ** - [out] the sink
  341. //
  342. // Output:
  343. // HRESULT
  344. //
  345. // Notes;
  346. //
  347. STDMETHODIMP COleControl::GetAdvise
  348. (
  349. DWORD *pdwAspects,
  350. DWORD *pdwAdviseFlags,
  351. IAdviseSink **ppAdviseSink
  352. )
  353. {
  354. // if they want it, give it to them
  355. //
  356. if (pdwAspects)
  357. *pdwAspects = DVASPECT_CONTENT;
  358. if (pdwAdviseFlags) {
  359. *pdwAdviseFlags = 0;
  360. if (m_fViewAdviseOnlyOnce) *pdwAdviseFlags |= ADVF_ONLYONCE;
  361. if (m_fViewAdvisePrimeFirst) *pdwAdviseFlags |= ADVF_PRIMEFIRST;
  362. }
  363. if (ppAdviseSink) {
  364. *ppAdviseSink = m_pViewAdviseSink;
  365. ADDREF_OBJECT(*ppAdviseSink);
  366. }
  367. return S_OK;
  368. }
  369. //=--------------------------------------------------------------------------=
  370. // COleControl::GetExtent [IViewObject2]
  371. //=--------------------------------------------------------------------------=
  372. // Returns the size that the control will be drawn on the
  373. // specified target device.
  374. //
  375. // Parameters:
  376. // DWORD - [in] draw aspect
  377. // LONG - [in] part of object to draw
  378. // DVTARGETDEVICE * - [in] information about target device
  379. // LPSIZEL - [out] where to put the size
  380. //
  381. // Output:
  382. // HRESULT
  383. //
  384. // Notes:
  385. //
  386. STDMETHODIMP COleControl::GetExtent
  387. (
  388. DWORD dwDrawAspect,
  389. LONG lindex,
  390. DVTARGETDEVICE *ptd,
  391. LPSIZEL psizel
  392. )
  393. {
  394. // we already have an implementation of this [from IOleObject]
  395. //
  396. return GetExtent(dwDrawAspect, psizel);
  397. }
  398. //=--------------------------------------------------------------------------=
  399. // COleControl::OnGetPalette [overridable]
  400. //=--------------------------------------------------------------------------=
  401. // called when the host wants palette information. ideally, people should use
  402. // this sparingly and carefully.
  403. //
  404. // Parameters:
  405. // HDC - [in] HIC for the target device
  406. // LOGPALETTE ** - [out] where to put the palette
  407. //
  408. // Output:
  409. // BOOL - TRUE means we processed it, false means nope.
  410. //
  411. // Notes:
  412. //
  413. BOOL COleControl::OnGetPalette
  414. (
  415. HDC hicTargetDevice,
  416. LOGPALETTE **ppColorSet
  417. )
  418. {
  419. return FALSE;
  420. }
  421. //=--------------------------------------------------------------------------=
  422. // COleControl::GetRect [IViewObjectEx]
  423. //=--------------------------------------------------------------------------=
  424. // returns a rectnagle describing a given drawing aspect
  425. //
  426. // Parameters:
  427. // DWORD - [in] aspect
  428. // LPRECTL - [out] region rectangle
  429. //
  430. // Output:
  431. // HRESULT
  432. //
  433. // Notes:
  434. //
  435. STDMETHODIMP COleControl::GetRect
  436. (
  437. DWORD dvAspect,
  438. LPRECTL prcRect
  439. )
  440. {
  441. RECTL rc;
  442. BOOL f;
  443. // call the user routine and let them return the size
  444. //
  445. f = OnGetRect(dvAspect, &rc);
  446. if (!f) return DV_E_DVASPECT;
  447. // transform these dudes.
  448. //
  449. PixelToHiMetric((LPSIZEL)&rc, (LPSIZEL)prcRect);
  450. PixelToHiMetric((LPSIZEL)((LPBYTE)&rc + sizeof(SIZEL)), (LPSIZEL)((LPBYTE)prcRect + sizeof(SIZEL)));
  451. return S_OK;
  452. }
  453. //=--------------------------------------------------------------------------=
  454. // COleControl::GetViewStatus [IViewObjectEx]
  455. //=--------------------------------------------------------------------------=
  456. // returns information about the opactiy of the object and what drawing
  457. // aspects are supported
  458. //
  459. // Parameters:
  460. // DWORD * - [out] the status
  461. //
  462. /// Output:
  463. // HRESULT
  464. //
  465. // Notes:
  466. //
  467. STDMETHODIMP COleControl::GetViewStatus
  468. (
  469. DWORD *pdwStatus
  470. )
  471. {
  472. // depending on the flag in the CONTROLOBJECTINFO structure, indicate our
  473. // transparency vs opacity.
  474. // OVERRIDE: controls that wish to support multi-pass drawing should
  475. // override this routine and return, in addition to the flags indication
  476. // opacity, flags indicating what sort of drawing aspects they support.
  477. //
  478. *pdwStatus = FCONTROLISOPAQUE(m_ObjectType) ? VIEWSTATUS_OPAQUE : 0;
  479. return S_OK;
  480. }
  481. //=--------------------------------------------------------------------------=
  482. // COleControl::QueryHitPoint [IViewObjectEx]
  483. //=--------------------------------------------------------------------------=
  484. // indicates whether a point is within a given aspect of an object.
  485. //
  486. // Parameters:
  487. // DWORD - [in] aspect
  488. // LPCRECT - [in] Bounds rectangle
  489. // POINT - [in] hit location client coordinates
  490. // LONG - [in] what the container considers close
  491. // DWORD * - [out] info about the hit
  492. //
  493. // Output:
  494. // HRESULT
  495. //
  496. // Notes:
  497. //
  498. STDMETHODIMP COleControl::QueryHitPoint
  499. (
  500. DWORD dvAspect,
  501. LPCRECT prcBounds,
  502. POINT ptLocation,
  503. LONG lCloseHint,
  504. DWORD *pdwHitResult
  505. )
  506. {
  507. // OVERRIDE: override me if you want to provide additional [non-opaque]
  508. // functionality
  509. //
  510. if (dvAspect != DVASPECT_CONTENT)
  511. return DV_E_DVASPECT;
  512. *pdwHitResult = PtInRect(prcBounds, ptLocation) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
  513. return S_OK;
  514. }
  515. //=--------------------------------------------------------------------------=
  516. // COleControl::QueryHitRect [IViewObjectEx]
  517. //=--------------------------------------------------------------------------=
  518. // indicates wheter any point in a rectangle is within a given drawing aspect
  519. // of an object.
  520. //
  521. // Parameters:
  522. // DWORD - [in] aspect
  523. // LPCRECT - [in] bounds
  524. // LPCRECT - [in] location
  525. // LONG - [in] what host considers close
  526. // DWORD * - [out] hit result
  527. //
  528. // Output:
  529. // HRESULT
  530. //
  531. // Notes:
  532. //
  533. STDMETHODIMP COleControl::QueryHitRect
  534. (
  535. DWORD dvAspect,
  536. LPCRECT prcBounds,
  537. LPCRECT prcLocation,
  538. LONG lCloseHint,
  539. DWORD *pdwHitResult
  540. )
  541. {
  542. RECT rc;
  543. // OVERRIDE: override this for additional behaviour
  544. //
  545. if (dvAspect != DVASPECT_CONTENT)
  546. return DV_E_DVASPECT;
  547. *pdwHitResult = IntersectRect(&rc, prcBounds, prcLocation) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
  548. return S_OK;
  549. }
  550. //=--------------------------------------------------------------------------=
  551. // COleControl::GetNaturalExtent [IViewObjectEx]
  552. //=--------------------------------------------------------------------------=
  553. // supports two types of control sizing, content and integral.
  554. //
  555. // Parameters:
  556. // DWORD - [in] aspect
  557. // LONG - [in] index
  558. // DVTARGETDEVICE * - [in] target device information
  559. // HDC - [in] HIC
  560. // DVEXTENTINFO * - [in] sizing data
  561. // LPSIZEL - [out] sizing data retunred by control
  562. //
  563. // Output:
  564. // HRESULT
  565. //
  566. // Notes:
  567. //
  568. STDMETHODIMP COleControl::GetNaturalExtent
  569. (
  570. DWORD dvAspect,
  571. LONG lIndex,
  572. DVTARGETDEVICE *ptd,
  573. HDC hicTargetDevice,
  574. DVEXTENTINFO *pExtentInfo,
  575. LPSIZEL pSizel
  576. )
  577. {
  578. return E_NOTIMPL;
  579. }
  580. //=--------------------------------------------------------------------------=
  581. // COleControl::OnGetRect [overridable
  582. //=--------------------------------------------------------------------------=
  583. // returns our rectangle
  584. //
  585. // Parameters:
  586. // DWORD - [in] aspect they want the rect for
  587. // RECTL * - [out] the rectangle that matches this aspect
  588. //
  589. // Output:
  590. // BOOL - false means we don't like the aspect
  591. //
  592. // Notes:
  593. //
  594. BOOL COleControl::OnGetRect
  595. (
  596. DWORD dvAspect,
  597. RECTL *pRect
  598. )
  599. {
  600. // by default, we only support content drawing.
  601. //
  602. if (dvAspect != DVASPECT_CONTENT)
  603. return FALSE;
  604. // just give them our bounding rectangle
  605. //
  606. *((LPRECT)pRect) = m_rcLocation;
  607. return TRUE;
  608. }
  609. //=--------------------------------------------------------------------------=
  610. // _CreateOleDC
  611. //=--------------------------------------------------------------------------=
  612. // creates an HDC given a DVTARGETDEVICE structure.
  613. //
  614. // Parameters:
  615. // DVTARGETDEVICE * - [in] duh.
  616. //
  617. // Output:
  618. // HDC
  619. //
  620. // Notes:
  621. //
  622. HDC _CreateOleDC
  623. (
  624. DVTARGETDEVICE *ptd
  625. )
  626. {
  627. LPDEVMODEW pDevModeW;
  628. DEVMODEA DevModeA, *pDevModeA;
  629. LPOLESTR lpwszDriverName;
  630. LPOLESTR lpwszDeviceName;
  631. LPOLESTR lpwszPortName;
  632. HDC hdc;
  633. // return screen DC for NULL target device
  634. //
  635. if (!ptd)
  636. return CreateDC("DISPLAY", NULL, NULL, NULL);
  637. if (ptd->tdExtDevmodeOffset == 0)
  638. pDevModeW = NULL;
  639. else
  640. pDevModeW = (LPDEVMODEW)((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  641. lpwszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  642. lpwszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  643. lpwszPortName = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  644. MAKE_ANSIPTR_FROMWIDE(pszDriverName, lpwszDriverName);
  645. MAKE_ANSIPTR_FROMWIDE(pszDeviceName, lpwszDeviceName);
  646. MAKE_ANSIPTR_FROMWIDE(pszPortName, lpwszPortName);
  647. if (pDevModeW) {
  648. WideCharToMultiByte(CP_ACP, 0, pDevModeW->dmDeviceName, -1, (LPSTR)DevModeA.dmDeviceName, CCHDEVICENAME, NULL, NULL);
  649. memcpy(&DevModeA.dmSpecVersion, &pDevModeW->dmSpecVersion,
  650. offsetof(DEVMODEA, dmFormName) - offsetof(DEVMODEA, dmSpecVersion));
  651. WideCharToMultiByte(CP_ACP, 0, pDevModeW->dmFormName, -1, (LPSTR)DevModeA.dmFormName, CCHFORMNAME, NULL, NULL);
  652. memcpy(&DevModeA.dmLogPixels, &pDevModeW->dmLogPixels, sizeof(DEVMODEA) - offsetof(DEVMODEA, dmLogPixels));
  653. if (pDevModeW->dmDriverExtra) {
  654. pDevModeA = (DEVMODEA *)HeapAlloc(g_hHeap, 0, sizeof(DEVMODEA) + pDevModeW->dmDriverExtra);
  655. if (!pDevModeA) return NULL;
  656. memcpy(pDevModeA, &DevModeA, sizeof(DEVMODEA));
  657. memcpy(pDevModeA + 1, pDevModeW + 1, pDevModeW->dmDriverExtra);
  658. } else
  659. pDevModeA = &DevModeA;
  660. DevModeA.dmSize = sizeof(DEVMODEA);
  661. } else
  662. pDevModeA = NULL;
  663. hdc = CreateDC(pszDriverName, pszDeviceName, pszPortName, pDevModeA);
  664. if (pDevModeA != &DevModeA) HeapFree(g_hHeap, 0, pDevModeA);
  665. return hdc;
  666. }