GdipButton.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. //
  2. // GdipButton.cpp : Version 1.0 - see article at CodeProject.com
  3. //
  4. // Author: Darren Sessions
  5. //
  6. //
  7. // Description:
  8. // GdipButton is a CButton derived control that uses GDI+
  9. // to support alternate image formats
  10. //
  11. // History
  12. // Version 1.0 - 2008 June 10
  13. // - Initial public release
  14. //
  15. // License:
  16. // This software is released under the Code Project Open License (CPOL),
  17. // which may be found here: http://www.codeproject.com/info/eula.aspx
  18. // You are free to use this software in any way you like, except that you
  19. // may not sell this source code.
  20. //
  21. // This software is provided "as is" with no expressed or implied warranty.
  22. // I accept no liability for any damage or loss of business that this
  23. // software may cause.
  24. //
  25. ///////////////////////////////////////////////////////////////////////////////
  26. #include "stdafx.h"
  27. #include "GdipButton.h"
  28. #include "CGdiPlusBitmap.h"
  29. #include "MemDC.h"
  30. #include "CP_Main.h"
  31. #ifdef _DEBUG
  32. #define new DEBUG_NEW
  33. #undef THIS_FILE
  34. static char THIS_FILE[] = __FILE__;
  35. #endif
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CGdipButton
  38. CGdipButton::CGdipButton()
  39. {
  40. m_pStdImage = NULL;
  41. m_pAltImage = NULL;
  42. m_bHaveBitmaps = FALSE;
  43. m_bHaveAltImage = FALSE;
  44. m_pCurBtn = NULL;
  45. m_bIsDisabled = FALSE;
  46. m_bIsToggle = FALSE;
  47. m_bIsHovering = FALSE;
  48. m_bIsTracking = FALSE;
  49. m_nCurType = STD_TYPE;
  50. m_pToolTip = NULL;
  51. }
  52. CGdipButton::~CGdipButton()
  53. {
  54. if(m_pStdImage) delete m_pStdImage;
  55. if(m_pAltImage) delete m_pAltImage;
  56. if(m_pToolTip) delete m_pToolTip;
  57. }
  58. BEGIN_MESSAGE_MAP(CGdipButton, CButton)
  59. //{{AFX_MSG_MAP(CGdipButton)
  60. ON_WM_DRAWITEM()
  61. ON_WM_ERASEBKGND()
  62. ON_WM_CTLCOLOR_REFLECT()
  63. ON_WM_MOUSEMOVE()
  64. ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
  65. ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
  66. //}}AFX_MSG_MAP
  67. END_MESSAGE_MAP()
  68. BOOL CGdipButton::LoadStdImageDPI(UINT id96, UINT id120, UINT id144, UINT id168, UINT id192, LPCTSTR pType)
  69. {
  70. BOOL ret = FALSE;
  71. if (theApp.m_metrics.GetDPIX() >= 192)
  72. {
  73. ret = LoadStdImage(id192, pType);
  74. }
  75. else if (theApp.m_metrics.GetDPIX() >= 168)
  76. {
  77. ret = LoadStdImage(id168, pType);
  78. }
  79. else if (theApp.m_metrics.GetDPIX() >= 144)
  80. {
  81. ret = LoadStdImage(id144, pType);
  82. }
  83. else if (theApp.m_metrics.GetDPIX() >= 120)
  84. {
  85. ret = LoadStdImage(id120, pType);
  86. }
  87. else
  88. {
  89. ret = LoadStdImage(id96, pType);
  90. }
  91. return ret;
  92. }
  93. //=============================================================================
  94. //
  95. // LoadStdImage()
  96. //
  97. // Purpose: The LoadStdImage() Loads the image for the button. This
  98. // function must be called at a minimum or the button wont do
  99. // anything.
  100. //
  101. // Parameters:
  102. // [IN] id
  103. // resource id, one of the resources already imported with the
  104. // resource editor, usually begins with IDR_
  105. //
  106. // [IN] pType
  107. // pointer to string describing the resource type
  108. //
  109. // Returns: BOOL
  110. // Non zero if successful, otherwise zero
  111. //
  112. //=============================================================================
  113. BOOL CGdipButton::LoadStdImage(UINT id, LPCTSTR pType)
  114. {
  115. m_pStdImage = new CGdiPlusBitmapResource;
  116. return m_pStdImage->Load(id, pType);
  117. }
  118. void CGdipButton::Test(CString c)
  119. {
  120. m_pStdImage = new CGdiPlusBitmapResource;
  121. m_pStdImage->Loads(c);
  122. }
  123. //=============================================================================
  124. //
  125. // LoadAltImage()
  126. //
  127. // Purpose: The LoadAltImage() Loads the altername image for the button.
  128. // This function call is optional
  129. // Parameters:
  130. // [IN] id
  131. // resource id, one of the resources already imported with the
  132. // resource editor, usually begins with IDR_
  133. //
  134. // [IN] pType
  135. // pointer to string describing the resource type
  136. //
  137. // Returns: BOOL
  138. // Non zero if successful, otherwise zero
  139. //
  140. //=============================================================================
  141. BOOL CGdipButton::LoadAltImage(UINT id, LPCTSTR pType)
  142. {
  143. m_bHaveAltImage = TRUE;
  144. m_pAltImage = new CGdiPlusBitmapResource;
  145. return (m_pAltImage->Load(id, pType));
  146. }
  147. //=============================================================================
  148. //
  149. // The framework calls this member function when a child control is about to
  150. // be drawn. All the bitmaps are created here on the first call. Every thing
  151. // is done with a memory DC except the background, which get's it's information
  152. // from the parent. The background is needed for transparent portions of PNG
  153. // images. An always on top app (such as Task Manager) that is in the way can
  154. // cause it to get an incorrect background. To avoid this, the parent should
  155. // call the SetBkGnd function with a memory DC when it creates the background.
  156. //
  157. //=============================================================================
  158. HBRUSH CGdipButton::CtlColor(CDC* pScreenDC, UINT nCtlColor)
  159. {
  160. if(!m_bHaveBitmaps)
  161. {
  162. if(!m_pStdImage)
  163. {
  164. return NULL; // Load the standard image with LoadStdImage()
  165. }
  166. CBitmap bmp, *pOldBitmap;
  167. CRect rect;
  168. GetClientRect(rect);
  169. // do everything with mem dc
  170. CMemDCEx pDC(pScreenDC, rect);
  171. Gdiplus::Graphics graphics(pDC->m_hDC);
  172. // background
  173. if (m_dcBk.m_hDC == NULL)
  174. {
  175. CRect rect1;
  176. CClientDC clDC(GetParent());
  177. GetWindowRect(rect1);
  178. GetParent()->ScreenToClient(rect1);
  179. m_dcBk.CreateCompatibleDC(&clDC);
  180. bmp.CreateCompatibleBitmap(&clDC, rect.Width(), rect.Height());
  181. pOldBitmap = m_dcBk.SelectObject(&bmp);
  182. m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), &clDC, rect1.left, rect1.top, SRCCOPY);
  183. bmp.DeleteObject();
  184. }
  185. // standard image
  186. if (m_dcStd.m_hDC == NULL)
  187. {
  188. PaintBk(pDC);
  189. /*graphics.DrawImage(*m_pStdImage, 0, 0);
  190. m_dcStd.CreateCompatibleDC(pDC);
  191. bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  192. pOldBitmap = m_dcStd.SelectObject(&bmp);
  193. m_dcStd.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
  194. bmp.DeleteObject();*/
  195. float width = (float)m_pStdImage->m_pBitmap->GetWidth();
  196. float height = (float)m_pStdImage->m_pBitmap->GetHeight();
  197. RectF grect; grect.X = 0, grect.Y = 0; grect.Width = width; grect.Height = height;
  198. graphics.DrawImage(*m_pStdImage, grect, 0, 0, width, height, UnitPixel);
  199. m_dcStd.CreateCompatibleDC(pDC);
  200. bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  201. pOldBitmap = m_dcStd.SelectObject(&bmp);
  202. m_dcStd.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
  203. bmp.DeleteObject();
  204. // standard image pressed
  205. if (m_dcStdP.m_hDC == NULL)
  206. {
  207. PaintBk(pDC);
  208. graphics.DrawImage(*m_pStdImage, 1, 1);
  209. m_dcStdP.CreateCompatibleDC(pDC);
  210. bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  211. pOldBitmap = m_dcStdP.SelectObject(&bmp);
  212. m_dcStdP.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
  213. bmp.DeleteObject();
  214. }
  215. // standard image hot
  216. if(m_dcStdH.m_hDC == NULL)
  217. {
  218. PaintBk(pDC);
  219. ColorMatrix HotMat = { 1.05f, 0.00f, 0.00f, 0.00f, 0.00f,
  220. 0.00f, 1.05f, 0.00f, 0.00f, 0.00f,
  221. 0.00f, 0.00f, 1.05f, 0.00f, 0.00f,
  222. 0.00f, 0.00f, 0.00f, 1.00f, 0.00f,
  223. 0.05f, 0.05f, 0.05f, 0.00f, 1.00f };
  224. ImageAttributes ia;
  225. ia.SetColorMatrix(&HotMat);
  226. float width = (float)m_pStdImage->m_pBitmap->GetWidth();
  227. float height = (float)m_pStdImage->m_pBitmap->GetHeight();
  228. RectF grect; grect.X=0, grect.Y=0; grect.Width = width; grect.Height = height;
  229. graphics.DrawImage(*m_pStdImage, grect, 0, 0, width, height, UnitPixel, &ia);
  230. m_dcStdH.CreateCompatibleDC(pDC);
  231. bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  232. pOldBitmap = m_dcStdH.SelectObject(&bmp);
  233. m_dcStdH.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
  234. bmp.DeleteObject();
  235. }
  236. // grayscale image
  237. if(m_dcGS.m_hDC == NULL)
  238. {
  239. PaintBk(pDC);
  240. ColorMatrix GrayMat = { 0.30f, 0.30f, 0.30f, 0.00f, 0.00f,
  241. 0.59f, 0.59f, 0.59f, 0.00f, 0.00f,
  242. 0.11f, 0.11f, 0.11f, 0.00f, 0.00f,
  243. 0.00f, 0.00f, 0.00f, 1.00f, 0.00f,
  244. 0.00f, 0.00f, 0.00f, 0.00f, 1.00f };
  245. ImageAttributes ia;
  246. ia.SetColorMatrix(&GrayMat);
  247. float width = (float)m_pStdImage->m_pBitmap->GetWidth();
  248. float height = (float)m_pStdImage->m_pBitmap->GetHeight();
  249. RectF grect; grect.X=0, grect.Y=0; grect.Width = width; grect.Height = height;
  250. graphics.DrawImage(*m_pStdImage, grect, 0, 0, width, height, UnitPixel, &ia);
  251. m_dcGS.CreateCompatibleDC(pDC);
  252. bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  253. pOldBitmap = m_dcGS.SelectObject(&bmp);
  254. m_dcGS.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
  255. bmp.DeleteObject();
  256. }
  257. }
  258. // alternate image
  259. if( (m_dcAlt.m_hDC == NULL) && m_bHaveAltImage )
  260. {
  261. PaintBk(pDC);
  262. graphics.DrawImage(*m_pAltImage, 0, 0);
  263. m_dcAlt.CreateCompatibleDC(pDC);
  264. bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  265. pOldBitmap = m_dcAlt.SelectObject(&bmp);
  266. m_dcAlt.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
  267. bmp.DeleteObject();
  268. // alternate image pressed
  269. if( (m_dcAltP.m_hDC == NULL) && m_bHaveAltImage )
  270. {
  271. PaintBk(pDC);
  272. graphics.DrawImage(*m_pAltImage, 1, 1);
  273. m_dcAltP.CreateCompatibleDC(pDC);
  274. bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  275. pOldBitmap = m_dcAltP.SelectObject(&bmp);
  276. m_dcAltP.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
  277. bmp.DeleteObject();
  278. }
  279. // alternate image hot
  280. if(m_dcAltH.m_hDC == NULL)
  281. {
  282. PaintBk(pDC);
  283. ColorMatrix HotMat = { 1.05f, 0.00f, 0.00f, 0.00f, 0.00f,
  284. 0.00f, 1.05f, 0.00f, 0.00f, 0.00f,
  285. 0.00f, 0.00f, 1.05f, 0.00f, 0.00f,
  286. 0.00f, 0.00f, 0.00f, 1.00f, 0.00f,
  287. 0.05f, 0.05f, 0.05f, 0.00f, 1.00f };
  288. ImageAttributes ia;
  289. ia.SetColorMatrix(&HotMat);
  290. float width = (float)m_pStdImage->m_pBitmap->GetWidth();
  291. float height = (float)m_pStdImage->m_pBitmap->GetHeight();
  292. RectF grect; grect.X=0, grect.Y=0; grect.Width = width; grect.Height = height;
  293. graphics.DrawImage(*m_pAltImage, grect, 0, 0, width, height, UnitPixel, &ia);
  294. m_dcAltH.CreateCompatibleDC(pDC);
  295. bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  296. pOldBitmap = m_dcAltH.SelectObject(&bmp);
  297. m_dcAltH.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
  298. bmp.DeleteObject();
  299. }
  300. }
  301. if(m_pCurBtn == NULL)
  302. {
  303. m_pCurBtn = &m_dcStd;
  304. }
  305. m_bHaveBitmaps = TRUE;
  306. }
  307. return NULL;
  308. }
  309. //=============================================================================
  310. // paint the background
  311. //=============================================================================
  312. void CGdipButton::PaintBk(CDC *pDC)
  313. {
  314. CRect rect;
  315. GetClientRect(rect);
  316. pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_dcBk, 0, 0, SRCCOPY);
  317. }
  318. //=============================================================================
  319. // paint the bitmap currently pointed to with m_pCurBtn
  320. //=============================================================================
  321. void CGdipButton::PaintBtn(CDC *pDC)
  322. {
  323. CRect rect;
  324. GetClientRect(rect);
  325. pDC->BitBlt(0, 0, rect.Width(), rect.Height(), m_pCurBtn, 0, 0, SRCCOPY);
  326. }
  327. //=============================================================================
  328. // enables the toggle mode
  329. // returns if it doesn't have the alternate image
  330. //=============================================================================
  331. void CGdipButton::EnableToggle(BOOL bEnable)
  332. {
  333. if(!m_bHaveAltImage) return;
  334. m_bIsToggle = bEnable;
  335. // this actually makes it start in the std state since toggle is called before paint
  336. if(bEnable) m_pCurBtn = &m_dcAlt;
  337. else m_pCurBtn = &m_dcStd;
  338. }
  339. //=============================================================================
  340. // sets the image type and disabled state then repaints
  341. //=============================================================================
  342. void CGdipButton::SetImage(int type)
  343. {
  344. m_nCurType = type;
  345. (type == DIS_TYPE) ? m_bIsDisabled = TRUE : m_bIsDisabled = FALSE;
  346. Invalidate();
  347. }
  348. //=============================================================================
  349. // set the control to owner draw
  350. //=============================================================================
  351. void CGdipButton::PreSubclassWindow()
  352. {
  353. // Set control to owner draw
  354. ModifyStyle(0, BS_OWNERDRAW, SWP_FRAMECHANGED);
  355. CButton::PreSubclassWindow();
  356. }
  357. //=============================================================================
  358. // disable double click
  359. //=============================================================================
  360. BOOL CGdipButton::PreTranslateMessage(MSG* pMsg)
  361. {
  362. if (pMsg->message == WM_LBUTTONDBLCLK)
  363. pMsg->message = WM_LBUTTONDOWN;
  364. if (m_pToolTip != NULL)
  365. {
  366. if (::IsWindow(m_pToolTip->m_hWnd))
  367. {
  368. m_pToolTip->RelayEvent(pMsg);
  369. }
  370. }
  371. return CButton::PreTranslateMessage(pMsg);
  372. }
  373. //=============================================================================
  374. // overide the erase function
  375. //=============================================================================
  376. BOOL CGdipButton::OnEraseBkgnd(CDC* pDC)
  377. {
  378. return TRUE;
  379. }
  380. //=============================================================================
  381. // Paint the button depending on the state of the mouse
  382. //=============================================================================
  383. void CGdipButton::DrawItem(LPDRAWITEMSTRUCT lpDIS)
  384. {
  385. CDC* pDC = CDC::FromHandle(lpDIS->hDC);
  386. // handle disabled state
  387. if(m_bIsDisabled)
  388. {
  389. m_pCurBtn = &m_dcGS;
  390. PaintBtn(pDC);
  391. return;
  392. }
  393. BOOL bIsPressed = (lpDIS->itemState & ODS_SELECTED);
  394. // handle toggle button
  395. if(m_bIsToggle && bIsPressed)
  396. {
  397. (m_nCurType == STD_TYPE) ? m_nCurType = ALT_TYPE : m_nCurType = STD_TYPE;
  398. }
  399. if(bIsPressed)
  400. {
  401. if(m_nCurType == STD_TYPE)
  402. m_pCurBtn = &m_dcStdP;
  403. else
  404. m_pCurBtn = &m_dcAltP;
  405. }
  406. else if(m_bIsHovering)
  407. {
  408. if(m_nCurType == STD_TYPE)
  409. m_pCurBtn = &m_dcStdH;
  410. else
  411. m_pCurBtn = &m_dcAltH;
  412. }
  413. else
  414. {
  415. if(m_nCurType == STD_TYPE)
  416. m_pCurBtn = &m_dcStd;
  417. else
  418. m_pCurBtn = &m_dcAlt;
  419. }
  420. // paint the button
  421. PaintBtn(pDC);
  422. }
  423. //=============================================================================
  424. LRESULT CGdipButton::OnMouseHover(WPARAM wparam, LPARAM lparam)
  425. //=============================================================================
  426. {
  427. m_bIsHovering = TRUE;
  428. Invalidate();
  429. DeleteToolTip();
  430. // Create a new Tooltip with new Button Size and Location
  431. SetToolTipText(m_tooltext);
  432. if (m_pToolTip != NULL)
  433. {
  434. if (::IsWindow(m_pToolTip->m_hWnd))
  435. {
  436. //Display ToolTip
  437. m_pToolTip->Update();
  438. }
  439. }
  440. return 0;
  441. }
  442. //=============================================================================
  443. LRESULT CGdipButton::OnMouseLeave(WPARAM wparam, LPARAM lparam)
  444. //=============================================================================
  445. {
  446. m_bIsTracking = FALSE;
  447. m_bIsHovering = FALSE;
  448. Invalidate();
  449. return 0;
  450. }
  451. //=============================================================================
  452. void CGdipButton::OnMouseMove(UINT nFlags, CPoint point)
  453. //=============================================================================
  454. {
  455. if (!m_bIsTracking)
  456. {
  457. TRACKMOUSEEVENT tme;
  458. tme.cbSize = sizeof(tme);
  459. tme.hwndTrack = m_hWnd;
  460. tme.dwFlags = TME_LEAVE|TME_HOVER;
  461. tme.dwHoverTime = 1;
  462. m_bIsTracking = _TrackMouseEvent(&tme);
  463. }
  464. CButton::OnMouseMove(nFlags, point);
  465. }
  466. //=============================================================================
  467. //
  468. // Call this member function with a memory DC from the code that paints
  469. // the parents background. Passing the screen DC defeats the purpose of
  470. // using this function.
  471. //
  472. //=============================================================================
  473. void CGdipButton::SetBkGnd(CDC* pDC)
  474. {
  475. CRect rect, rectS;
  476. CBitmap bmp, *pOldBitmap;
  477. GetClientRect(rect);
  478. GetWindowRect(rectS);
  479. GetParent()->ScreenToClient(rectS);
  480. m_dcBk.DeleteDC();
  481. m_dcBk.CreateCompatibleDC(pDC);
  482. bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  483. pOldBitmap = m_dcBk.SelectObject(&bmp);
  484. m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, rectS.left, rectS.top, SRCCOPY);
  485. bmp.DeleteObject();
  486. }
  487. //=============================================================================
  488. // Set the tooltip with a string resource
  489. //=============================================================================
  490. void CGdipButton::SetToolTipText(UINT nId, BOOL bActivate)
  491. {
  492. // load string resource
  493. m_tooltext.LoadString(nId);
  494. // If string resource is not empty
  495. if (m_tooltext.IsEmpty() == FALSE)
  496. {
  497. SetToolTipText(m_tooltext, bActivate);
  498. }
  499. }
  500. //=============================================================================
  501. // Set the tooltip with a CString
  502. //=============================================================================
  503. void CGdipButton::SetToolTipText(CString spText, BOOL bActivate)
  504. {
  505. // We cannot accept NULL pointer
  506. if (spText.IsEmpty()) return;
  507. // Initialize ToolTip
  508. InitToolTip();
  509. m_tooltext = spText;
  510. // If there is no tooltip defined then add it
  511. if (m_pToolTip->GetToolCount() == 0)
  512. {
  513. CRect rectBtn;
  514. GetClientRect(rectBtn);
  515. m_pToolTip->AddTool(this, m_tooltext, rectBtn, 1);
  516. }
  517. // Set text for tooltip
  518. m_pToolTip->UpdateTipText(m_tooltext, this, 1);
  519. m_pToolTip->SetDelayTime(2000);
  520. m_pToolTip->Activate(bActivate);
  521. }
  522. //=============================================================================
  523. void CGdipButton::InitToolTip()
  524. //=============================================================================
  525. {
  526. if (m_pToolTip == NULL)
  527. {
  528. m_pToolTip = new CToolTipCtrl;
  529. // Create ToolTip control
  530. m_pToolTip->Create(this);
  531. m_pToolTip->Activate(TRUE);
  532. }
  533. }
  534. //=============================================================================
  535. void CGdipButton::DeleteToolTip()
  536. //=============================================================================
  537. {
  538. // Destroy Tooltip incase the size of the button has changed.
  539. if (m_pToolTip != NULL)
  540. {
  541. delete m_pToolTip;
  542. m_pToolTip = NULL;
  543. }
  544. }