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.

691 lines
16 KiB

  1. //+---------------------------------------------------------------------
  2. //
  3. // File: border.cxx
  4. //
  5. // Contents: Border Object Class
  6. //
  7. // Classes: OLEBorder
  8. //
  9. //------------------------------------------------------------------------
  10. #include "headers.hxx"
  11. #pragma hdrstop
  12. BOOL OLEBorder::fInit = FALSE;
  13. HCURSOR OLEBorder::ahc[5] = { NULL, NULL, NULL, NULL, NULL };
  14. int OLEBorder::iPartMap[14] = {
  15. ICURS_STD, // 0 NOWHERE
  16. ICURS_STD, // 1 TOP
  17. ICURS_STD, // 2 RIGHT
  18. ICURS_STD, // 3 BOTTOM
  19. ICURS_STD, // 4 LEFT
  20. ICURS_NESW, // 5 TOPRIGHT
  21. ICURS_NWSE, // 6 BOTTOMRIGHT
  22. ICURS_NESW, // 7 BOTTOMLEFT
  23. ICURS_NWSE, // 8 TOPLEFT
  24. ICURS_NS, // 9 TOPHAND
  25. ICURS_WE, //10 RIGHTHAND
  26. ICURS_NS, //11 BOTTOMHAND
  27. ICURS_WE, //12 LEFTHAND
  28. ICURS_STD //13 INSIDE
  29. };
  30. HCURSOR
  31. OLEBorder::MapPartToCursor(USHORT usPart)
  32. {
  33. if (usPart > MAX_OBPART)
  34. usPart = 0;
  35. return ahc[iPartMap[usPart]];
  36. }
  37. //+---------------------------------------------------------------
  38. //
  39. // Member: OLEBorder::InitClass
  40. //
  41. //---------------------------------------------------------------
  42. void
  43. OLEBorder::InitClass( void )
  44. {
  45. _fErased = TRUE;
  46. _state = 0;
  47. _sThickness = FBORDER_THICKNESS;
  48. _sMinHeight = FBORDER_MINHEIGHT;
  49. _sMinWidth = FBORDER_MINWIDTH;
  50. if(fInit)
  51. return;
  52. ahc[ICURS_NWSE] = LoadCursor( NULL, IDC_SIZENWSE );
  53. ahc[ICURS_NESW] = LoadCursor( NULL, IDC_SIZENESW );
  54. ahc[ICURS_NS] = LoadCursor( NULL, IDC_SIZENS );
  55. ahc[ICURS_WE] = LoadCursor( NULL, IDC_SIZEWE );
  56. ahc[ICURS_STD] = LoadCursor( NULL, IDC_SIZEALL );
  57. fInit = TRUE;
  58. }
  59. //+---------------------------------------------------------------
  60. //
  61. // Member: OLEBorder::OLEBorder
  62. //
  63. //---------------------------------------------------------------
  64. OLEBorder::OLEBorder( void )
  65. {
  66. rect.top = 0;
  67. rect.left = 0;
  68. rect.bottom = 0;
  69. rect.right = 0;
  70. InitClass();
  71. }
  72. //+---------------------------------------------------------------
  73. //
  74. // Member: OLEBorder::OLEBorder
  75. //
  76. //---------------------------------------------------------------
  77. OLEBorder::OLEBorder( RECT& r )
  78. {
  79. rect = r;
  80. InitClass();
  81. }
  82. //+---------------------------------------------------------------
  83. //
  84. // Member: OLEBorder::~OLEBorder
  85. //
  86. //---------------------------------------------------------------
  87. OLEBorder::~OLEBorder( void )
  88. {
  89. }
  90. //+---------------------------------------------------------------
  91. //
  92. // Member: OLEBorder::SetState
  93. //
  94. //---------------------------------------------------------------
  95. USHORT
  96. OLEBorder::SetState( HDC hdc, HWND hwnd, USHORT usBorderState )
  97. {
  98. if (_state ^ usBorderState)
  99. {
  100. if (hdc != NULL)
  101. {
  102. _state |= OBSTYLE_RESERVED;
  103. Draw(hdc,hwnd);
  104. }
  105. }
  106. _state = usBorderState & (~OBSTYLE_RESERVED);
  107. if (hdc != NULL)
  108. Draw(hdc,hwnd);
  109. return _state;
  110. }
  111. //+---------------------------------------------------------------
  112. //
  113. // Member: OLEBorder::Erase
  114. //
  115. //---------------------------------------------------------------
  116. void
  117. OLEBorder::Erase(HWND hwnd)
  118. {
  119. RECT r;
  120. if (hwnd != NULL && !_fErased)
  121. {
  122. _fErased = TRUE;
  123. if(_state & OBSTYLE_DIAGONAL_FILL)
  124. {
  125. GetBorderRect(r,BP_INSIDE);
  126. InvalidateRect(hwnd,&r,TRUE);
  127. }
  128. else
  129. {
  130. for(int i = BP_TOP; i <= BP_LEFT; i++)
  131. {
  132. GetBorderRect(r,i);
  133. InvalidateRect(hwnd,&r,TRUE);
  134. }
  135. }
  136. }
  137. _state = _state & OBSTYLE_INSIDE;
  138. }
  139. void
  140. OLEBorder::GetInsideBorder( RECT& rDest, int iEdge )
  141. {
  142. int sHalf = _sThickness >> 1;
  143. int sMid;
  144. switch(iEdge)
  145. {
  146. case BP_TOP:
  147. case BP_BOTTOM:
  148. rDest.left = rect.left;
  149. rDest.right = rect.right;
  150. if (iEdge == BP_TOP)
  151. {
  152. rDest.top = rect.top;
  153. rDest.bottom = rect.top + _sThickness;
  154. }
  155. else
  156. {
  157. rDest.top = rect.bottom - _sThickness;
  158. rDest.bottom = rect.bottom;
  159. }
  160. break;
  161. case BP_RIGHT:
  162. case BP_LEFT:
  163. rDest.top = rect.top;
  164. rDest.bottom = rect.bottom;
  165. if (iEdge == BP_RIGHT)
  166. {
  167. rDest.left = rect.right - _sThickness;
  168. rDest.right = rect.right;
  169. }
  170. else
  171. {
  172. rDest.left = rect.left;
  173. rDest.right = rect.left + _sThickness;
  174. }
  175. break;
  176. case BP_TOPRIGHT:
  177. case BP_BOTTOMRIGHT:
  178. rDest.left = rect.right - _sThickness;
  179. rDest.right = rect.right;
  180. if (iEdge == BP_TOPRIGHT)
  181. {
  182. rDest.top = rect.top;
  183. rDest.bottom = rect.top + _sThickness;
  184. }
  185. else
  186. {
  187. rDest.top = rect.bottom - _sThickness;
  188. rDest.bottom = rect.bottom;
  189. }
  190. break;
  191. case BP_BOTTOMLEFT:
  192. case BP_TOPLEFT:
  193. rDest.left = rect.left;
  194. rDest.right = rect.left + _sThickness;
  195. if (iEdge == BP_BOTTOMLEFT)
  196. {
  197. rDest.top = rect.bottom - _sThickness;
  198. rDest.bottom = rect.bottom;
  199. }
  200. else
  201. {
  202. rDest.top = rect.top;
  203. rDest.bottom = rect.top + _sThickness;
  204. }
  205. break;
  206. case BP_TOPHAND:
  207. case BP_BOTTOMHAND:
  208. sMid = rect.left + ((rect.right - rect.left) >> 1);
  209. rDest.left = sMid - sHalf;
  210. rDest.right = sMid + sHalf;
  211. if (iEdge == BP_TOPHAND)
  212. {
  213. rDest.top = rect.top;
  214. rDest.bottom = rect.top + _sThickness;
  215. }
  216. else
  217. {
  218. rDest.top = rect.bottom - _sThickness;
  219. rDest.bottom = rect.bottom;
  220. }
  221. break;
  222. case BP_RIGHTHAND:
  223. case BP_LEFTHAND:
  224. sMid = rect.top + ((rect.bottom - rect.top) >> 1);
  225. rDest.top = sMid - sHalf;
  226. rDest.bottom = sMid + sHalf;
  227. if (iEdge == BP_LEFTHAND)
  228. {
  229. rDest.left = rect.left;
  230. rDest.right = rect.left + _sThickness;
  231. }
  232. else
  233. {
  234. rDest.left = rect.right - _sThickness;
  235. rDest.right = rect.right;
  236. }
  237. break;
  238. case BP_INSIDE:
  239. default:
  240. rDest = rect;
  241. break;
  242. }
  243. }
  244. void
  245. OLEBorder::GetOutsideBorder( RECT& rDest, int iEdge )
  246. {
  247. int sHalf = _sThickness >> 1;
  248. int sMid;
  249. switch(iEdge)
  250. {
  251. case BP_TOP:
  252. case BP_BOTTOM:
  253. rDest.left = rect.left - _sThickness;
  254. rDest.right = rect.right + _sThickness;
  255. if (iEdge == BP_TOP)
  256. {
  257. rDest.top = rect.top - _sThickness;
  258. rDest.bottom = rect.top + 1;
  259. }
  260. else
  261. {
  262. rDest.top = rect.bottom;
  263. rDest.bottom = rect.bottom + _sThickness;
  264. }
  265. break;
  266. case BP_RIGHT:
  267. case BP_LEFT:
  268. rDest.top = rect.top - _sThickness;
  269. rDest.bottom = rect.bottom + _sThickness;
  270. if (iEdge == BP_RIGHT)
  271. {
  272. rDest.left = rect.right;
  273. rDest.right = rect.right + _sThickness;
  274. }
  275. else
  276. {
  277. rDest.left = rect.left - _sThickness;
  278. rDest.right = rect.left + 1;
  279. }
  280. break;
  281. case BP_TOPRIGHT:
  282. case BP_BOTTOMRIGHT:
  283. rDest.left = rect.right;
  284. rDest.right = rect.right + _sThickness;
  285. if (iEdge == BP_TOPRIGHT)
  286. {
  287. rDest.top = rect.top - _sThickness;
  288. rDest.bottom = rect.top + 1;
  289. }
  290. else
  291. {
  292. rDest.top = rect.bottom;
  293. rDest.bottom = rect.bottom + _sThickness;
  294. }
  295. break;
  296. case BP_BOTTOMLEFT:
  297. case BP_TOPLEFT:
  298. rDest.left = rect.left - _sThickness;
  299. rDest.right = rect.left + 1;
  300. if (iEdge == BP_BOTTOMLEFT)
  301. {
  302. rDest.top = rect.bottom;
  303. rDest.bottom = rect.bottom + _sThickness;
  304. }
  305. else
  306. {
  307. rDest.top = rect.top - _sThickness;
  308. rDest.bottom = rect.top + 1;
  309. }
  310. break;
  311. case BP_TOPHAND:
  312. case BP_BOTTOMHAND:
  313. sMid = rect.left + ((rect.right - rect.left) >> 1);
  314. rDest.left = sMid - sHalf;
  315. rDest.right = sMid + sHalf;
  316. if (iEdge == BP_TOPHAND)
  317. {
  318. rDest.top = rect.top - _sThickness;
  319. rDest.bottom = rect.top + 1;
  320. }
  321. else
  322. {
  323. rDest.top = rect.bottom;
  324. rDest.bottom = rect.bottom + _sThickness;
  325. }
  326. break;
  327. case BP_RIGHTHAND:
  328. case BP_LEFTHAND:
  329. sMid = rect.top + ((rect.bottom - rect.top) >> 1);
  330. rDest.top = sMid - sHalf;
  331. rDest.bottom = sMid + sHalf;
  332. if (iEdge == BP_LEFTHAND)
  333. {
  334. rDest.left = rect.left - _sThickness;
  335. rDest.right = rect.left + 1;
  336. }
  337. else
  338. {
  339. rDest.left = rect.right;
  340. rDest.right = rect.right + _sThickness;
  341. }
  342. break;
  343. case BP_INSIDE:
  344. default: //inactive border
  345. rDest.left = rect.left - 1;
  346. rDest.right = rect.right + 1;
  347. rDest.top = rect.top - 1;
  348. rDest.bottom = rect.bottom + 1;
  349. break;
  350. }
  351. }
  352. //+---------------------------------------------------------------
  353. //
  354. // Member: OLEBorder::GetBorderRect
  355. //
  356. //---------------------------------------------------------------
  357. void
  358. OLEBorder::GetBorderRect( RECT& rDest, int iEdge )
  359. {
  360. if(_state & OBSTYLE_INSIDE)
  361. GetInsideBorder(rDest,iEdge);
  362. else
  363. GetOutsideBorder(rDest,iEdge);
  364. }
  365. //+---------------------------------------------------------------
  366. //
  367. // Member: OLEBorder::SwitchCoords
  368. //
  369. //---------------------------------------------------------------
  370. void
  371. OLEBorder::SwitchCoords( HWND hwndFrom, HWND hwndTo )
  372. {
  373. MapWindowPoints(hwndFrom, hwndTo, (LPPOINT)&rect, 2);
  374. MapWindowPoints(hwndFrom, hwndTo, &_pt, 1);
  375. }
  376. //+---------------------------------------------------------------
  377. //
  378. // Member: OLEBorder::Draw
  379. //
  380. //---------------------------------------------------------------
  381. void
  382. OLEBorder::Draw( HDC hdc, HWND hwnd )
  383. {
  384. if(hdc == NULL || (_state & ~OBSTYLE_INSIDE) == 0)
  385. {
  386. return; //nothing to do!
  387. }
  388. RECT r;
  389. //
  390. // the following should be rewritten so any border style
  391. // can be drawn in XOR mode...
  392. //
  393. if (_state & OBSTYLE_XOR)
  394. {
  395. if (_state & OBSTYLE_THICK)
  396. {
  397. PatBlt(hdc, rect.left - 1, rect.top - 1,
  398. rect.right - rect.left + 2, 3, PATINVERT);
  399. PatBlt(hdc, rect.left - 1, rect.bottom - 2,
  400. rect.right - rect.left + 2, 3, PATINVERT);
  401. PatBlt(hdc, rect.left - 1, rect.top + 2,
  402. 3, rect.bottom - rect.top - 4, PATINVERT);
  403. PatBlt(hdc, rect.right - 2, rect.top + 2,
  404. 3, rect.bottom - rect.top - 4, PATINVERT);
  405. }
  406. else
  407. DrawFocusRect(hdc,&rect);
  408. return;
  409. }
  410. HBRUSH hbrBlack = (HBRUSH)GetStockObject(BLACK_BRUSH);
  411. HBRUSH hbr;
  412. COLORREF clrref;
  413. int i;
  414. if (_state & OBSTYLE_RESERVED)
  415. {
  416. Erase(hwnd);
  417. return;
  418. }
  419. if (_state & OBSTYLE_ACTIVE)
  420. {
  421. clrref = GetSysColor(COLOR_ACTIVECAPTION);
  422. }
  423. else
  424. {
  425. clrref = GetSysColor(COLOR_WINDOWFRAME);
  426. }
  427. if ((_state & OBSTYLE_TYPEMASK) == OBSTYLE_DIAGONAL_FILL)
  428. {
  429. hbr = CreateHatchBrush(HS_DIAGCROSS,clrref);
  430. GetBorderRect(r,BP_INSIDE);
  431. FillRect(hdc,&r,hbr);
  432. DeleteObject(hbr);
  433. }
  434. else if ((_state & OBSTYLE_TYPEMASK) == OBSTYLE_SOLID_PEN)
  435. {
  436. GetBorderRect(r,BP_INSIDE);
  437. FrameRect(hdc,&r,hbrBlack);
  438. }
  439. if (_state & OBSTYLE_THICK)
  440. {
  441. if (_state & OBSTYLE_INSIDE)
  442. InflateRect(&r,-1,-1);
  443. else
  444. InflateRect(&r,1,1);
  445. FrameRect(hdc,&rect,hbrBlack);
  446. }
  447. if (_state & OBSTYLE_HANDLED)
  448. {
  449. for (i = BP_TOPRIGHT; i <= BP_TOPLEFT; i++)
  450. {
  451. GetBorderRect(r,i);
  452. FillRect(hdc,&r,hbrBlack);
  453. }
  454. for (i = BP_TOPHAND; i <= BP_LEFTHAND; i++)
  455. {
  456. GetBorderRect(r,i);
  457. FillRect(hdc,&r,hbrBlack);
  458. }
  459. }
  460. _fErased = FALSE;
  461. }
  462. //+---------------------------------------------------------------
  463. //
  464. // Member: OLEBorder::QueryHit
  465. //
  466. //---------------------------------------------------------------
  467. USHORT
  468. OLEBorder::QueryHit( POINT point )
  469. {
  470. RECT r = rect;
  471. USHORT usWhere = BP_NOWHERE;
  472. if ((_state & OBSTYLE_INSIDE) == 0)
  473. InflateRect(&r,_sThickness,_sThickness);
  474. if (PtInRect(&r,point))
  475. {
  476. usWhere = BP_INSIDE;
  477. //
  478. //test against the real inside to optimize this case...
  479. //
  480. InflateRect(&r,-_sThickness,-_sThickness);
  481. //
  482. // PtInRect counts the top and left borders as being inside, so
  483. // we must account for this.
  484. //
  485. r.left++;
  486. r.top++;
  487. if (!PtInRect(&r,point))
  488. {
  489. //
  490. //Search for the "handle" that was hit...
  491. //
  492. USHORT i;
  493. for (i = BP_LEFTHAND; i >= BP_TOP; i--)
  494. {
  495. GetBorderRect(r,i);
  496. if (PtInRect(&r,point))
  497. {
  498. usWhere = i;
  499. break;
  500. }
  501. }
  502. }
  503. }
  504. return(usWhere);
  505. }
  506. //+---------------------------------------------------------------
  507. //
  508. // Member: OLEBorder::QueryMoveCursor
  509. //
  510. //---------------------------------------------------------------
  511. HCURSOR
  512. OLEBorder::QueryMoveCursor( POINT ptCurrent, BOOL fMustMove )
  513. {
  514. //
  515. //Stash part-hit info so we can do the right thing durring
  516. //upcomming move/size operation
  517. //
  518. if (fMustMove)
  519. {
  520. _usPart = BP_INSIDE;
  521. }
  522. else
  523. {
  524. _usPart = QueryHit(ptCurrent);
  525. }
  526. return MapPartToCursor(_usPart);
  527. }
  528. //+---------------------------------------------------------------
  529. //
  530. // Member: OLEBorder::BeginMove
  531. //
  532. //---------------------------------------------------------------
  533. HCURSOR
  534. OLEBorder::BeginMove( HDC hdc, HWND hwnd, POINT ptStart,
  535. BOOL fMustMove )
  536. {
  537. if(_state == 0 )
  538. _state = OBSTYLE_SOLID_PEN;
  539. SetState( hdc, hwnd, _state | OBSTYLE_XOR | OBSTYLE_THICK);
  540. _pt = ptStart;
  541. return QueryMoveCursor(ptStart,fMustMove);
  542. }
  543. //+---------------------------------------------------------------
  544. //
  545. // Member: OLEBorder::UpdateMove
  546. //
  547. //---------------------------------------------------------------
  548. RECT&
  549. OLEBorder::UpdateMove( HDC hdc, HWND hwnd, POINT ptCurrent, BOOL fNewRegion )
  550. {
  551. if ((ptCurrent.x == _pt.x) && (ptCurrent.y == _pt.y))
  552. return rect;
  553. RECT rTemp = rect;
  554. Draw(hdc,hwnd);
  555. if (fNewRegion)
  556. {
  557. rTemp.left = min(_pt.x,ptCurrent.x);
  558. rTemp.top = min(_pt.y,ptCurrent.y);
  559. rTemp.right = max(_pt.x,ptCurrent.x);
  560. rTemp.bottom = max(_pt.y,ptCurrent.y);
  561. }
  562. else
  563. {
  564. int xDelta = ptCurrent.x - _pt.x;
  565. int yDelta = ptCurrent.y - _pt.y;
  566. switch (_usPart)
  567. {
  568. case BP_INSIDE:
  569. case BP_TOP:
  570. case BP_BOTTOM:
  571. case BP_RIGHT:
  572. case BP_LEFT:
  573. default:
  574. OffsetRect(&rTemp,xDelta,yDelta);
  575. break;
  576. case BP_TOPRIGHT:
  577. rTemp.right += xDelta;
  578. rTemp.top += yDelta;
  579. break;
  580. case BP_BOTTOMRIGHT:
  581. rTemp.right += xDelta;
  582. rTemp.bottom += yDelta;
  583. break;
  584. case BP_BOTTOMLEFT:
  585. rTemp.bottom += yDelta;
  586. rTemp.left += xDelta;
  587. break;
  588. case BP_TOPLEFT:
  589. rTemp.top += yDelta;
  590. rTemp.left += xDelta;
  591. break;
  592. case BP_TOPHAND:
  593. rTemp.top += yDelta;
  594. break;
  595. case BP_BOTTOMHAND:
  596. rTemp.bottom += yDelta;
  597. break;
  598. case BP_RIGHTHAND:
  599. rTemp.right += xDelta;
  600. break;
  601. case BP_LEFTHAND:
  602. rTemp.left += xDelta;
  603. break;
  604. }
  605. }
  606. //
  607. //clip resize to repect minimum height & width specification
  608. //
  609. if((rTemp.right - rTemp.left >= _sMinWidth) &&
  610. (rTemp.bottom - rTemp.top >= _sMinHeight))
  611. {
  612. rect = rTemp;
  613. if (!fNewRegion)
  614. {
  615. _pt = ptCurrent;
  616. }
  617. }
  618. Draw(hdc,hwnd);
  619. return rect;
  620. }
  621. //+---------------------------------------------------------------
  622. //
  623. // Member: OLEBorder::EndMove
  624. //
  625. //---------------------------------------------------------------
  626. RECT&
  627. OLEBorder::EndMove( HDC hdc, HWND hwnd, POINT ptCurrent, USHORT usBorderState )
  628. {
  629. SetState( hdc, hwnd, usBorderState );
  630. return rect;
  631. }