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.

942 lines
24 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // icobutt.c - icon button functions
  24. ////
  25. #include "winlocal.h"
  26. #include "icobutt.h"
  27. #include "gfx.h"
  28. #include "mem.h"
  29. #include "str.h"
  30. #include "sys.h"
  31. #include "trace.h"
  32. ////
  33. // private definitions
  34. ////
  35. // dimensions of standard Windows icon
  36. //
  37. #define ICONWIDTH 32
  38. #define ICONHEIGHT 32
  39. // icobutt control struct
  40. //
  41. typedef struct ICOBUTT
  42. {
  43. DWORD dwVersion;
  44. HINSTANCE hInst;
  45. HTASK hTask;
  46. DWORD dwFlags;
  47. HICON hIconMono;
  48. HICON hIconColor;
  49. HICON hIconGreyed;
  50. HFONT hFont;
  51. HWND hwndButton;
  52. } ICOBUTT, FAR *LPICOBUTT;
  53. // helper functions
  54. //
  55. static int IcoButtDrawFace(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem);
  56. static int IcoButtDrawEdges(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem);
  57. static int IcoButtDrawIcon(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem);
  58. static int IcoButtDrawText(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem);
  59. static int IcoButtDrawLine(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem,
  60. LPTSTR lpszLine, int nLine);
  61. static LPICOBUTT IcoButtGetPropPtr(HWND hwndButton);
  62. static int IcoButtSetPropPtr(HWND hwndButton, LPICOBUTT lpIcoButt);
  63. static LPICOBUTT IcoButtRemovePropPtr(HWND hwndButton);
  64. static LPICOBUTT IcoButtGetPtr(HICOBUTT hIcoButt);
  65. static HICOBUTT IcoButtGetHandle(LPICOBUTT lpIcoButt);
  66. ////
  67. // public functions
  68. ////
  69. // IcoButtInit - initialize icon button
  70. // <hwndButton> (i) button window handle
  71. // NULL create new button
  72. // <dwVersion> (i) must be ICOBUTT_VERSION
  73. // <hInst> (i) instance handle of calling module
  74. // <id> (i) id of button
  75. // <hIconMono> (i) icon to display on mono displays
  76. // <hIconColor> (i) icon to display on color displays
  77. // 0 use mono icon
  78. // <hIconGreyed> (i) icon to display when button disabled
  79. // 0 use mono icon
  80. // <hFont> (i) font to use for text
  81. // NULL use variable-pitch system font (ANSI_VAR_FONT)
  82. // <lpszText> (i) button text string
  83. // <x> (i) button horizontal position
  84. // <y> (i) button vertical position
  85. // <cx> (i) button width
  86. // <cy> (i) button height
  87. // <hwndParent> (i) button parent
  88. // <dwFlags> (i) control flags
  89. // ICOBUTT_ICONCENTER draw icon centered above text (default)
  90. // ICOBUTT_ICONLEFT draw icon on the left side of text
  91. // ICOBUTT_ICONRIGHT draw icon on the right side of text
  92. // ICOBUTT_NOFOCUS do not draw control showing focus
  93. // ICOBUTT_NOTEXT do not draw any button text
  94. // ICOBUTT_SPLITTEXT split long text onto two rows if necessary
  95. // ICOBUTT_NOSIZE ignore <cx> and <cy> param
  96. // ICOBUTT_NOMOVE ignore <x> and <y> param
  97. // return handle (NULL if error)
  98. //
  99. // NOTE: if <hwndButton> is set to an existing button,
  100. // a new button is not created. Rather, only the icon button
  101. // control structure <hIcoButt> is created. This allows
  102. // existing buttons to be turned into an icon button.
  103. //
  104. HICOBUTT DLLEXPORT WINAPI IcoButtInit(HWND hwndButton,
  105. DWORD dwVersion, HINSTANCE hInst, UINT id,
  106. HICON hIconMono, HICON hIconColor, HICON hIconGreyed,
  107. HFONT hFont, LPTSTR lpszText, int x, int y, int cx, int cy,
  108. HWND hwndParent, DWORD dwFlags)
  109. {
  110. BOOL fSuccess = TRUE;
  111. LPICOBUTT lpIcoButt = NULL;
  112. DWORD dwStyle;
  113. if (hwndButton != NULL &&
  114. (lpIcoButt = IcoButtGetPropPtr(hwndButton)) != NULL)
  115. {
  116. // IcoButtInit() has already been used to initialize this button
  117. // so we need to call IcoButtTerm before continuing
  118. //
  119. if (IcoButtTerm(hwndButton, IcoButtGetHandle(lpIcoButt)) != 0)
  120. fSuccess = TraceFALSE(NULL);
  121. else
  122. lpIcoButt = NULL;
  123. }
  124. if (!fSuccess)
  125. ;
  126. else if (dwVersion != ICOBUTT_VERSION)
  127. fSuccess = TraceFALSE(NULL);
  128. else if (hInst == NULL)
  129. fSuccess = TraceFALSE(NULL);
  130. // at least this icon must be specified
  131. //
  132. else if (hIconMono == NULL)
  133. fSuccess = TraceFALSE(NULL);
  134. // memory is allocated such that the client app owns it
  135. //
  136. else if (lpIcoButt == NULL &&
  137. (lpIcoButt = (LPICOBUTT) MemAlloc(NULL, sizeof(ICOBUTT), 0)) == NULL)
  138. {
  139. fSuccess = TraceFALSE(NULL);
  140. }
  141. else
  142. {
  143. lpIcoButt->hwndButton = hwndButton;
  144. lpIcoButt->dwVersion = dwVersion;
  145. lpIcoButt->hInst = hInst;
  146. lpIcoButt->hTask = GetCurrentTask();
  147. lpIcoButt->dwFlags = dwFlags;
  148. lpIcoButt->hFont =
  149. (hFont == NULL ? GetStockObject(ANSI_VAR_FONT) : hFont);
  150. lpIcoButt->hIconMono = hIconMono;
  151. lpIcoButt->hIconColor = hIconColor;
  152. lpIcoButt->hIconGreyed = hIconGreyed;
  153. }
  154. // if icon button does not yet exist...
  155. //
  156. if (fSuccess && hwndButton == NULL)
  157. {
  158. // create an icon button window
  159. //
  160. if ((lpIcoButt->hwndButton = CreateWindowEx(
  161. 0L,
  162. TEXT("Button"),
  163. lpszText,
  164. BS_OWNERDRAW | WS_POPUP,
  165. x, y, cx, cy,
  166. hwndParent,
  167. (HMENU)IntToPtr(id),
  168. lpIcoButt->hInst,
  169. NULL)) == NULL)
  170. {
  171. fSuccess = TraceFALSE(NULL);
  172. }
  173. // store icobutt pointer as window property
  174. //
  175. else if (IcoButtSetPropPtr(lpIcoButt->hwndButton, lpIcoButt) != 0)
  176. fSuccess = TraceFALSE(NULL);
  177. // show the window AFTER setting window property because
  178. // lpIcoButt is needed by IconButtDraw() to draw the button
  179. //
  180. else
  181. ShowWindow(lpIcoButt->hwndButton, SW_SHOW);
  182. }
  183. // else if icon button already exists...
  184. //
  185. else if (fSuccess && hwndButton != NULL)
  186. {
  187. // make sure the button style is owner drawn
  188. //
  189. if ((dwStyle = (DWORD)
  190. GetWindowLongPtr(lpIcoButt->hwndButton, GWL_STYLE)) == 0L)
  191. fSuccess = TraceFALSE(NULL);
  192. else if (SetWindowLongPtr(lpIcoButt->hwndButton,
  193. GWL_STYLE, BS_OWNERDRAW | dwStyle) == 0L)
  194. fSuccess = TraceFALSE(NULL);
  195. // set window id
  196. //
  197. #ifdef _WIN32
  198. else if (SetWindowLongPtr(lpIcoButt->hwndButton, GWLP_ID, id) == 0)
  199. #else
  200. else if (SetWindowWordPtr(lpIcoButt->hwndButton, GWWP_ID, id) == 0)
  201. #endif
  202. fSuccess = TraceFALSE(NULL);
  203. // set window size
  204. //
  205. else if (!(dwFlags & ICOBUTT_NOSIZE) &&
  206. !SetWindowPos(lpIcoButt->hwndButton, NULL, 0, 0, cx, cy,
  207. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER))
  208. fSuccess = TraceFALSE(NULL);
  209. // set window position
  210. //
  211. else if (!(dwFlags & ICOBUTT_NOMOVE) &&
  212. !SetWindowPos(lpIcoButt->hwndButton, NULL, x, y, 0, 0,
  213. SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOZORDER))
  214. fSuccess = TraceFALSE(NULL);
  215. // store icobutt pointer as window property
  216. //
  217. else if (IcoButtSetPropPtr(lpIcoButt->hwndButton, lpIcoButt) != 0)
  218. fSuccess = TraceFALSE(NULL);
  219. else
  220. {
  221. // set window parent
  222. //
  223. SetParent(lpIcoButt->hwndButton, hwndParent);
  224. // set window text AFTER setting window property because
  225. // lpIcoButt is needed by IconButtDraw() to draw the button
  226. //
  227. SetWindowText(lpIcoButt->hwndButton, lpszText);
  228. }
  229. }
  230. if (!fSuccess)
  231. {
  232. IcoButtTerm(hwndButton, IcoButtGetHandle(lpIcoButt));
  233. lpIcoButt = NULL;
  234. }
  235. return fSuccess ? IcoButtGetHandle(lpIcoButt) : NULL;
  236. }
  237. // IcoButtTerm - terminate icon button
  238. // <hwndButton> (i) button window handle
  239. // NULL destroy window
  240. // <hIcoButt> (i) handle returned from IcoButtCreate
  241. // return 0 if success
  242. //
  243. // NOTE: if <hwndButton> is set to an existing button,
  244. // the button is not destroyed. Rather, only the icon button
  245. // control structure <hIcoButt> is destroyed. This allows
  246. // IcoButtInit() to be called again for the same button.
  247. //
  248. int DLLEXPORT WINAPI IcoButtTerm(HWND hwndButton, HICOBUTT hIcoButt)
  249. {
  250. BOOL fSuccess = TRUE;
  251. LPICOBUTT lpIcoButt;
  252. if ((lpIcoButt = IcoButtGetPtr(hIcoButt)) == NULL)
  253. fSuccess = TraceFALSE(NULL);
  254. else
  255. {
  256. if (IcoButtRemovePropPtr(lpIcoButt->hwndButton) == NULL)
  257. fSuccess = TraceFALSE(NULL);
  258. if (hwndButton == NULL &&
  259. lpIcoButt->hwndButton != NULL &&
  260. !DestroyWindow(lpIcoButt->hwndButton))
  261. fSuccess = TraceFALSE(NULL);
  262. else
  263. lpIcoButt->hwndButton = NULL;
  264. if ((lpIcoButt = MemFree(NULL, lpIcoButt)) != NULL)
  265. fSuccess = TraceFALSE(NULL);
  266. }
  267. return fSuccess ? 0 : -1;
  268. }
  269. // IcoButtDraw - draw icon button
  270. // <lpDrawItem> (i) structure describing how to draw control
  271. // return 0 if success
  272. //
  273. int DLLEXPORT WINAPI IcoButtDraw(const LPDRAWITEMSTRUCT lpDrawItem)
  274. {
  275. BOOL fSuccess = TRUE;
  276. LPICOBUTT lpIcoButt;
  277. // retrieve icobutt pointer from button handle
  278. //
  279. if ((lpIcoButt = IcoButtGetPropPtr(lpDrawItem->hwndItem)) == NULL)
  280. fSuccess = TraceFALSE(NULL);
  281. // draw the button face
  282. //
  283. else if (IcoButtDrawFace(lpIcoButt, lpDrawItem) != 0)
  284. fSuccess = TraceFALSE(NULL);
  285. // draw the button edges
  286. //
  287. else if (IcoButtDrawEdges(lpIcoButt, lpDrawItem) != 0)
  288. fSuccess = TraceFALSE(NULL);
  289. // draw the button icon
  290. //
  291. else if (IcoButtDrawIcon(lpIcoButt, lpDrawItem) != 0)
  292. fSuccess = TraceFALSE(NULL);
  293. // draw the button text
  294. //
  295. else if (IcoButtDrawText(lpIcoButt, lpDrawItem) != 0)
  296. fSuccess = TraceFALSE(NULL);
  297. return fSuccess ? 0 : -1;
  298. }
  299. // IcoButtDrawFace - draw the button face
  300. // <lpIcoButt> (i) pointer to ICOBUTT structure
  301. // <lpDrawItem> (i) structure describing how to draw control
  302. // return 0 if success
  303. //
  304. static int IcoButtDrawFace(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem)
  305. {
  306. BOOL fSuccess = TRUE;
  307. HDC hdc = lpDrawItem->hDC;
  308. RECT rc = lpDrawItem->rcItem;
  309. HBRUSH hbr = NULL;
  310. HBRUSH hbrOld;
  311. // use the default button face color
  312. //
  313. if ((hbr = CreateSolidBrush(GetSysColor(COLOR_BTNFACE))) == NULL)
  314. fSuccess = TraceFALSE(NULL);
  315. else if ((hbrOld = SelectObject(hdc, hbr)) == NULL)
  316. fSuccess = TraceFALSE(NULL);
  317. else if (FillRect(hdc, &rc, hbr), FALSE)
  318. fSuccess = TraceFALSE(NULL);
  319. else if (SelectObject(hdc, hbrOld) == NULL)
  320. fSuccess = TraceFALSE(NULL);
  321. if (hbr != NULL && !DeleteObject(hbr))
  322. fSuccess = TraceFALSE(NULL);
  323. else
  324. hbr = NULL;
  325. return fSuccess ? 0 : -1;
  326. }
  327. // IcoButtDrawEdges - draw the button edges
  328. // <lpIcoButt> (i) pointer to ICOBUTT structure
  329. // <lpDrawItem> (i) structure describing how to draw control
  330. // return 0 if success
  331. //
  332. static int IcoButtDrawEdges(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem)
  333. {
  334. BOOL fSuccess = TRUE;
  335. HDC hdc = lpDrawItem->hDC;
  336. RECT rc = lpDrawItem->rcItem;
  337. UINT itemState = lpDrawItem->itemState;
  338. int iColor;
  339. HPEN hPen = NULL;
  340. HPEN hPenOld;
  341. // Draw a black frame border
  342. //
  343. //
  344. // We should verify the value returned by GetStockObject
  345. HBRUSH hBrush = (HBRUSH)GetStockObject( BLACK_BRUSH );
  346. if( hBrush )
  347. FrameRect(hdc, &rc, hBrush);
  348. // draw top and left edges of button to give depth
  349. //
  350. if (itemState & ODS_SELECTED)
  351. iColor = COLOR_BTNSHADOW;
  352. #if WINVER >= 0x030A
  353. else if (SysGetWindowsVersion() >= 310)
  354. iColor = COLOR_BTNHIGHLIGHT;
  355. #endif
  356. else
  357. iColor = COLOR_WINDOW;
  358. if ((hPen = CreatePen(PS_SOLID, 1, GetSysColor(iColor))) == NULL)
  359. fSuccess = TraceFALSE(NULL);
  360. else if ((hPenOld = SelectObject(hdc, hPen)) == NULL)
  361. fSuccess = TraceFALSE(NULL);
  362. else
  363. {
  364. MoveToEx(hdc, 1, 1, NULL);
  365. LineTo(hdc, rc.right - 1, 1);
  366. MoveToEx(hdc, 1, 1, NULL);
  367. LineTo(hdc, 1, rc.bottom - 1);
  368. MoveToEx(hdc, 2, 2, NULL);
  369. LineTo(hdc, rc.right - 2, 2);
  370. MoveToEx(hdc, 2, 2, NULL);
  371. LineTo(hdc, 2, rc.bottom - 2);
  372. if (SelectObject(hdc, hPenOld) == NULL)
  373. fSuccess = TraceFALSE(NULL);
  374. }
  375. if (hPen != NULL && !DeleteObject(hPen))
  376. fSuccess = TraceFALSE(NULL);
  377. else
  378. hPen = NULL;
  379. // draw bottom and right edges of button to give depth
  380. //
  381. if (fSuccess && !(itemState & ODS_SELECTED))
  382. {
  383. iColor = COLOR_BTNSHADOW;
  384. if ((hPen = CreatePen(PS_SOLID, 1, GetSysColor(iColor))) == NULL)
  385. fSuccess = TraceFALSE(NULL);
  386. else if ((hPenOld = SelectObject(hdc, hPen)) == NULL)
  387. fSuccess = TraceFALSE(NULL);
  388. else
  389. {
  390. MoveToEx(hdc, rc.right - 2, rc.bottom - 2, NULL);
  391. LineTo(hdc, rc.right - 2, 1);
  392. MoveToEx(hdc, rc.right - 2, rc.bottom - 2, NULL);
  393. LineTo(hdc, 1, rc.bottom - 2);
  394. MoveToEx(hdc, rc.right - 3, rc.bottom - 3, NULL);
  395. LineTo(hdc, rc.right - 3, 2);
  396. MoveToEx(hdc, rc.right - 3, rc.bottom - 3, NULL);
  397. LineTo(hdc, 2, rc.bottom - 3);
  398. if (SelectObject(hdc, hPenOld) == NULL)
  399. fSuccess = TraceFALSE(NULL);
  400. }
  401. }
  402. if (hPen != NULL && !DeleteObject(hPen))
  403. fSuccess = TraceFALSE(NULL);
  404. else
  405. hPen = NULL;
  406. return fSuccess ? 0 : -1;
  407. }
  408. // IcoButtDrawIcon - draw the button icon
  409. // <lpIcoButt> (i) pointer to ICOBUTT structure
  410. // <lpDrawItem> (i) structure describing how to draw control
  411. // return 0 if success
  412. //
  413. static int IcoButtDrawIcon(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem)
  414. {
  415. BOOL fSuccess = TRUE;
  416. HDC hdc = lpDrawItem->hDC;
  417. RECT rc = lpDrawItem->rcItem;
  418. UINT itemState = lpDrawItem->itemState;
  419. HICON hIcon;
  420. int x;
  421. int y;
  422. // choose the appropriate icon
  423. //
  424. if (itemState & ODS_DISABLED)
  425. hIcon = lpIcoButt->hIconGreyed;
  426. else if (GfxDeviceIsMono(hdc))
  427. hIcon = lpIcoButt->hIconMono;
  428. else
  429. hIcon = lpIcoButt->hIconColor;
  430. if (hIcon == NULL)
  431. hIcon = lpIcoButt->hIconMono;
  432. // calculate horizontal position of icon
  433. //
  434. if (lpIcoButt->dwFlags & ICOBUTT_ICONLEFT)
  435. x = 1;
  436. else if (lpIcoButt->dwFlags & ICOBUTT_ICONRIGHT)
  437. x = max(0, rc.right - rc.left - ICONWIDTH);
  438. else // centered is the default
  439. x = max(0, rc.right - rc.left - ICONWIDTH) / 2;
  440. // calculate vertical position of icon
  441. //
  442. if ((lpIcoButt->dwFlags & ICOBUTT_NOTEXT) ||
  443. (lpIcoButt->dwFlags & ICOBUTT_SPLITTEXT))
  444. y = 1;
  445. else
  446. y = 3;
  447. // if button is depressed, adjust icon position down and to the right
  448. //
  449. if (itemState & ODS_SELECTED)
  450. {
  451. x += 2;
  452. y += 2;
  453. }
  454. // draw the icon
  455. //
  456. //
  457. // We should verify if hIcon is a valid resource handler
  458. //
  459. if ( (NULL == hIcon) || !DrawIcon(hdc, x, y, hIcon))
  460. fSuccess = TraceFALSE(NULL);
  461. // draw a rectangle around icon to indicate focus if needed
  462. //
  463. else if ((itemState & ODS_FOCUS) &&
  464. !(lpIcoButt->dwFlags & ICOBUTT_NOFOCUS) &&
  465. (lpIcoButt->dwFlags & ICOBUTT_NOTEXT))
  466. {
  467. RECT rcFocus;
  468. COLORREF crBkColorOld;
  469. rcFocus.left = x + 3;
  470. rcFocus.top = y + 3;
  471. rcFocus.right = x + ICONWIDTH - 3;
  472. rcFocus.bottom = y + ICONHEIGHT - 3;
  473. crBkColorOld = SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  474. DrawFocusRect(hdc, &rcFocus);
  475. SetBkColor(hdc, crBkColorOld);
  476. }
  477. return fSuccess ? 0 : -1;
  478. }
  479. // IcoButtDrawText - draw the button text
  480. // <lpIcoButt> (i) pointer to ICOBUTT structure
  481. // <lpDrawItem> (i) structure describing how to draw control
  482. // return 0 if success
  483. //
  484. static int IcoButtDrawText(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem)
  485. {
  486. BOOL fSuccess = TRUE;
  487. HDC hdc = lpDrawItem->hDC;
  488. TCHAR szText[64];
  489. *szText = '\0';
  490. Button_GetText(lpIcoButt->hwndButton, szText, SIZEOFARRAY(szText));
  491. if (*szText == '\0' || (lpIcoButt->dwFlags & ICOBUTT_NOTEXT))
  492. ; // no need to continue
  493. else
  494. {
  495. HFONT hFontOld;
  496. COLORREF crBkColorOld;
  497. COLORREF crTextColorOld;
  498. int nBkModeOld;
  499. if ((hFontOld = SelectObject(hdc, lpIcoButt->hFont)) == NULL)
  500. fSuccess = TraceFALSE(NULL);
  501. else
  502. {
  503. crBkColorOld = SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
  504. crTextColorOld = SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
  505. nBkModeOld = SetBkMode(hdc, TRANSPARENT);
  506. }
  507. if (fSuccess)
  508. {
  509. LPTSTR lpszLine = szText;
  510. int cLines = 0;
  511. if (lpIcoButt->dwFlags & ICOBUTT_SPLITTEXT)
  512. {
  513. // split text into lines, draw each one
  514. //
  515. lpszLine = StrTok(szText, TEXT("\t\n"));
  516. while (fSuccess && lpszLine != NULL)
  517. {
  518. if (IcoButtDrawLine(lpIcoButt, lpDrawItem,
  519. lpszLine, ++cLines) != 0)
  520. fSuccess = TraceFALSE(NULL);
  521. lpszLine = (LPTSTR) StrTok(NULL, TEXT("\t\n"));
  522. }
  523. }
  524. else
  525. {
  526. // draw entire text as one line
  527. //
  528. if (IcoButtDrawLine(lpIcoButt, lpDrawItem,
  529. lpszLine, 0) != 0)
  530. fSuccess = TraceFALSE(NULL);
  531. }
  532. }
  533. if (fSuccess)
  534. {
  535. // restore foreground and background text colors
  536. //
  537. SetBkColor(hdc, crBkColorOld);
  538. SetTextColor(hdc, crTextColorOld);
  539. SetBkMode(hdc, nBkModeOld);
  540. // restore font
  541. //
  542. if (SelectObject(hdc, hFontOld) == NULL)
  543. fSuccess = TraceFALSE(NULL);
  544. }
  545. }
  546. return fSuccess ? 0 : -1;
  547. }
  548. // IcoButtDrawLine - draw a line of button text
  549. // <lpIcoButt> (i) pointer to ICOBUTT structure
  550. // <lpDrawItem> (i) structure describing how to draw control
  551. // <lpszLine> (i) line of text to draw
  552. // <nLine> (i) line count
  553. // 0 one and only line
  554. // return 0 if success
  555. //
  556. static int IcoButtDrawLine(LPICOBUTT lpIcoButt, const LPDRAWITEMSTRUCT lpDrawItem,
  557. LPTSTR lpszLine, int nLine)
  558. {
  559. BOOL fSuccess = TRUE;
  560. HDC hdc = lpDrawItem->hDC;
  561. RECT rc = lpDrawItem->rcItem;
  562. UINT itemState = lpDrawItem->itemState;
  563. TEXTMETRIC tm;
  564. SIZE size;
  565. int cxTemp;
  566. //
  567. // We should initialize the local variables
  568. //
  569. int xUnderline = 0;
  570. int cxUnderline = 0;
  571. LPTSTR lpsz1;
  572. LPTSTR lpsz2;
  573. int cchLine;
  574. int x;
  575. int y;
  576. if (!GetTextMetrics(hdc, &tm))
  577. fSuccess = TraceFALSE(NULL);
  578. else
  579. {
  580. // determine position and width of underline
  581. //
  582. cxTemp = 0L;
  583. lpsz1 = lpsz2 = lpszLine;
  584. while (*lpsz2 != '\0')
  585. {
  586. if (*lpsz2 == '&' && *(lpsz2 + 1) != '\0')
  587. {
  588. xUnderline = cxTemp;
  589. lpsz2 = StrNextChr(lpsz2);
  590. cxUnderline = 0;
  591. if (GetTextExtentPoint(hdc, lpsz2, 1, &size))
  592. cxUnderline = size.cx;
  593. }
  594. else
  595. {
  596. if (GetTextExtentPoint(hdc, lpsz2, 1, &size))
  597. cxTemp += size.cx;
  598. *lpsz1 = *lpsz2;
  599. lpsz1 = StrNextChr(lpsz1);
  600. lpsz2 = StrNextChr(lpsz2);
  601. }
  602. }
  603. *lpsz1 = '\0';
  604. // determine width of text
  605. //
  606. cchLine = StrLen(lpszLine);
  607. cxTemp = 0;
  608. if (GetTextExtentPoint(hdc, lpszLine, cchLine, &size))
  609. cxTemp = size.cx;
  610. // calculate horizontal position of line
  611. //
  612. if (lpIcoButt->dwFlags & ICOBUTT_ICONLEFT)
  613. x = 1 + ICONWIDTH;
  614. else if (lpIcoButt->dwFlags & ICOBUTT_ICONRIGHT)
  615. x = max(0, rc.right - rc.left - cxTemp) - ICONWIDTH;
  616. else // centered is the default
  617. x = max(0, rc.right - rc.left - cxTemp) / 2;
  618. if ((lpIcoButt->dwFlags & ICOBUTT_ICONLEFT) ||
  619. (lpIcoButt->dwFlags & ICOBUTT_ICONRIGHT))
  620. {
  621. y = nLine == 0 ? 23 : nLine == 1 ? 17 : 29;
  622. }
  623. else // centered
  624. {
  625. if (lpIcoButt->dwFlags & ICOBUTT_SPLITTEXT)
  626. y = nLine == 0 ? 47 : nLine == 1 ? 42 : 53;
  627. else
  628. y = 50;
  629. }
  630. y -= tm.tmHeight;
  631. if (itemState & ODS_SELECTED)
  632. {
  633. x += 2;
  634. y += 2;
  635. }
  636. // draw the text
  637. //
  638. if (!(itemState & ODS_DISABLED))
  639. {
  640. if (!TextOut(hdc, x, y, lpszLine, cchLine))
  641. fSuccess = TraceFALSE(NULL);
  642. }
  643. else
  644. {
  645. COLORREF crGray;
  646. // if ((crGray = GetSysColor(COLOR_GRAYTEXT)) != 0)
  647. if ((crGray = GetSysColor(COLOR_BTNSHADOW)) != 0 &&
  648. crGray != GetSysColor(COLOR_BTNFACE) &&
  649. !GfxDeviceIsMono(hdc))
  650. {
  651. COLORREF crTextOld;
  652. crTextOld = SetTextColor(hdc, crGray);
  653. if (!TextOut(hdc, x, y, lpszLine, cchLine))
  654. fSuccess = TraceFALSE(NULL);
  655. SetTextColor(hdc, crTextOld);
  656. }
  657. else
  658. {
  659. GrayString(hdc, GetStockObject(BLACK_BRUSH),
  660. NULL, (LPARAM) lpszLine, cchLine, x, y, 0, 0);
  661. }
  662. }
  663. // draw underline if necessary
  664. //
  665. if (cxUnderline > 0)
  666. {
  667. HPEN hPen = NULL;
  668. HPEN hPenOld = NULL;
  669. if ((itemState & ODS_DISABLED))
  670. {
  671. if ((hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW))) == NULL)
  672. fSuccess = TraceFALSE(NULL);
  673. else if ((hPenOld = SelectObject(hdc, hPen)) == NULL)
  674. fSuccess = TraceFALSE(NULL);
  675. }
  676. MoveToEx(hdc, x + xUnderline, y + tm.tmAscent + 1, NULL);
  677. LineTo(hdc, x + xUnderline + cxUnderline, y + tm.tmAscent + 1);
  678. if (hPenOld != NULL && SelectObject(hdc, hPenOld) == NULL)
  679. fSuccess = TraceFALSE(NULL);
  680. if (hPen != NULL && !DeleteObject(hPen))
  681. fSuccess = TraceFALSE(NULL);
  682. }
  683. // draw a rectangle around text to indicate focus if needed
  684. //
  685. if ((itemState & ODS_FOCUS) &&
  686. !(lpIcoButt->dwFlags & ICOBUTT_NOFOCUS))
  687. {
  688. RECT rcFocus;
  689. COLORREF crBkColorOld;
  690. rcFocus.left = x - 2;
  691. rcFocus.top = y - 1;
  692. rcFocus.right = x + cxTemp + 2;
  693. rcFocus.bottom = y + tm.tmHeight + 1;
  694. crBkColorOld = SetBkColor(hdc, GetSysColor(COLOR_WINDOW));
  695. DrawFocusRect(hdc, &rcFocus);
  696. SetBkColor(hdc, crBkColorOld);
  697. }
  698. }
  699. return fSuccess ? 0 : -1;
  700. }
  701. // IcoButtGetPropPtr - get icobutt pointer from button window property
  702. // <hwndButton> (i) button window handle
  703. // return ICOBUTT pointer (NULL if none)
  704. //
  705. static LPICOBUTT IcoButtGetPropPtr(HWND hwndButton)
  706. {
  707. BOOL fSuccess = TRUE;
  708. LPICOBUTT lpIcoButt;
  709. // retrieve button instance data, construct pointer
  710. //
  711. #ifdef _WIN32
  712. if ((lpIcoButt = (LPICOBUTT) GetProp(hwndButton, TEXT("lpIcoButt"))) == NULL)
  713. ; // window property does not exist
  714. #else
  715. WORD wSelector;
  716. WORD wOffset;
  717. wSelector = (WORD) GetProp(hwndButton, TEXT("lpIcoButtSELECTOR"));
  718. wOffset = (WORD) GetProp(hwndButton, TEXT("lpIcoButtOFFSET"));
  719. if ((lpIcoButt = MAKELP(wSelector, wOffset)) == NULL)
  720. ; // window property does not exist
  721. #endif
  722. else if (IsBadWritePtr(lpIcoButt, sizeof(ICOBUTT)))
  723. fSuccess = TraceFALSE(NULL);
  724. return fSuccess ? lpIcoButt : NULL;
  725. }
  726. // IcoButtSetPropPtr - set icobutt pointer as button window property
  727. // <hwndButton> (i) button window handle
  728. // <lpIcoButt> (i) pointer to ICOBUTT struct
  729. // return 0 if success
  730. //
  731. static int IcoButtSetPropPtr(HWND hwndButton, LPICOBUTT lpIcoButt)
  732. {
  733. BOOL fSuccess = TRUE;
  734. #ifdef _WIN32
  735. if (!SetProp(hwndButton, TEXT("lpIcoButt"), (HANDLE) lpIcoButt))
  736. fSuccess = TraceFALSE(NULL);
  737. #else
  738. if (!SetProp(hwndButton,
  739. TEXT("lpIcoButtSELECTOR"), (HANDLE) SELECTOROF(lpIcoButt)))
  740. fSuccess = TraceFALSE(NULL);
  741. else if (!SetProp(hwndButton,
  742. TEXT("lpIcoButtOFFSET"), (HANDLE) OFFSETOF(lpIcoButt)))
  743. fSuccess = TraceFALSE(NULL);
  744. #endif
  745. return fSuccess ? 0 : -1;
  746. }
  747. // IcoButtRemovePropPtr - remove icobutt pointer from button window property
  748. // <hwndButton> (i) button window handle
  749. // return 0 if success
  750. //
  751. static LPICOBUTT IcoButtRemovePropPtr(HWND hwndButton)
  752. {
  753. BOOL fSuccess = TRUE;
  754. LPICOBUTT lpIcoButt;
  755. // retrieve button instance data, construct pointer
  756. //
  757. #ifdef _WIN32
  758. if ((lpIcoButt = (LPICOBUTT) RemoveProp(hwndButton, TEXT("lpIcoButt"))) == NULL)
  759. ; // window property does not exist
  760. #else
  761. WORD wSelector;
  762. WORD wOffset;
  763. wSelector = (WORD) RemoveProp(hwndButton, TEXT("lpIcoButtSELECTOR"));
  764. wOffset = (WORD) RemoveProp(hwndButton, TEXT("lpIcoButtOFFSET"));
  765. if ((lpIcoButt = MAKELP(wSelector, wOffset)) == NULL)
  766. fSuccess = TraceFALSE(NULL);
  767. #endif
  768. return fSuccess ? lpIcoButt : NULL;
  769. }
  770. // IcoButtGetPtr - verify that icobutt handle is valid,
  771. // <hIcoButt> (i) handle returned from IcoButtCreate
  772. // return corresponding icobutt pointer (NULL if error)
  773. //
  774. static LPICOBUTT IcoButtGetPtr(HICOBUTT hIcoButt)
  775. {
  776. BOOL fSuccess = TRUE;
  777. LPICOBUTT lpIcoButt;
  778. if ((lpIcoButt = (LPICOBUTT) hIcoButt) == NULL)
  779. fSuccess = TraceFALSE(NULL);
  780. else if (IsBadWritePtr(lpIcoButt, sizeof(ICOBUTT)))
  781. fSuccess = TraceFALSE(NULL);
  782. #ifdef CHECKTASK
  783. // make sure current task owns the icobutt handle
  784. //
  785. else if (lpIcoButt->hTask != GetCurrentTask())
  786. fSuccess = TraceFALSE(NULL);
  787. #endif
  788. return fSuccess ? lpIcoButt : NULL;
  789. }
  790. // IcoButtGetHandle - verify that icobutt pointer is valid,
  791. // <lpIcoButt> (i) pointer to ICOBUTT struct
  792. // return corresponding icobutt handle (NULL if error)
  793. //
  794. static HICOBUTT IcoButtGetHandle(LPICOBUTT lpIcoButt)
  795. {
  796. BOOL fSuccess = TRUE;
  797. HICOBUTT hIcoButt;
  798. if ((hIcoButt = (HICOBUTT) lpIcoButt) == NULL)
  799. fSuccess = TraceFALSE(NULL);
  800. return fSuccess ? hIcoButt : NULL;
  801. }