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.

1480 lines
39 KiB

  1. /******************************************************************************/
  2. /* */
  3. /* Class Implementations in this file */
  4. /* CFloatImgToolWnd */
  5. /* CImgToolWnd */
  6. /* CToolboxWnd */
  7. /* CTool */
  8. /* */
  9. /******************************************************************************/
  10. #include "stdafx.h"
  11. #include "global.h"
  12. #include "pbrush.h"
  13. #include "pbrusfrm.h"
  14. #include "pbrusvw.h"
  15. #include "ipframe.h"
  16. #include "minifwnd.h"
  17. #include "bmobject.h"
  18. #include "imgsuprt.h"
  19. #include "imgwnd.h"
  20. #include "imgwell.h"
  21. #include "imgtools.h"
  22. #include "toolbox.h"
  23. #include "imgcolor.h"
  24. #include "docking.h"
  25. #include "t_Text.h"
  26. #define TRYANYTHING
  27. #ifdef _DEBUG
  28. #undef THIS_FILE
  29. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  30. #endif
  31. IMPLEMENT_DYNAMIC(CToolboxWnd, CControlBar)
  32. #include "memtrace.h"
  33. CImgToolWnd* NEAR g_pImgToolWnd = NULL;
  34. #define BPR(br, rop) \
  35. { dc.SelectObject((br)); \
  36. dc.PatBlt(rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, rop); }
  37. #define iidmMac ( sizeof (rgidm) / sizeof (rgidm[0]) )
  38. static UINT NEAR rgidm [] =
  39. {
  40. IDMB_PICKRGNTOOL,
  41. IDMB_PICKTOOL,
  42. IDMB_ERASERTOOL,
  43. IDMB_FILLTOOL,
  44. IDMY_PICKCOLOR,
  45. IDMB_ZOOMTOOL,
  46. IDMB_PENCILTOOL,
  47. IDMB_CBRUSHTOOL,
  48. IDMB_AIRBSHTOOL,
  49. IDMX_TEXTTOOL,
  50. IDMB_LINETOOL,
  51. IDMB_CURVETOOL,
  52. IDMB_RECTTOOL,
  53. IDMB_POLYGONTOOL,
  54. IDMB_ELLIPSETOOL,
  55. IDMB_RNDRECTTOOL
  56. };
  57. /******************************************************************************/
  58. BEGIN_MESSAGE_MAP(CImgToolWnd, CToolboxWnd)
  59. ON_WM_SYSCOLORCHANGE()
  60. ON_WM_ERASEBKGND()
  61. ON_WM_LBUTTONDOWN()
  62. ON_WM_LBUTTONDBLCLK()
  63. ON_WM_RBUTTONDOWN()
  64. ON_WM_PAINT()
  65. ON_WM_KEYDOWN()
  66. ON_WM_KEYUP()
  67. ON_WM_CHAR()
  68. ON_WM_NCHITTEST()
  69. END_MESSAGE_MAP()
  70. /******************************************************************************/
  71. HTHEME SafeOpenThemeData(HWND hwnd, LPCWSTR pszClassList)
  72. {
  73. __try
  74. {
  75. return OpenThemeData(hwnd, pszClassList);
  76. }
  77. __except(EXCEPTION_EXECUTE_HANDLER)
  78. {
  79. return 0;
  80. }
  81. }
  82. /******************************************************************************/
  83. BOOL CImgToolWnd::Create(const TCHAR* pWindowName, DWORD dwStyle,
  84. const RECT& rect, const POINT& btnSize, WORD wWide,
  85. CWnd* pParentWnd, BOOL bDkRegister)
  86. {
  87. if (! CToolboxWnd::Create( pWindowName, dwStyle, rect,
  88. btnSize, NUM_TOOLS_WIDE, pParentWnd, IDB_IMGTOOLS ))
  89. {
  90. return FALSE;
  91. }
  92. for (int iidm = 0; iidm < iidmMac; iidm += 1)
  93. {
  94. CTool* pTool = new CTool(this, (WORD)rgidm[iidm], iidm, TS_CMD | TS_STICKY,
  95. rgidm[iidm] == CImgTool::GetCurrentID() ? TF_DOWN : 0);
  96. if (pTool == NULL)
  97. {
  98. DestroyWindow();
  99. return FALSE;
  100. }
  101. AddTool(pTool);
  102. }
  103. m_nOffsetX = m_btnsize.x / 5;
  104. m_nOffsetY = m_btnsize.y / 5;
  105. CSize size = GetSize();
  106. MoveWindow( rect.left, rect.top, size.cx, size.cy );
  107. return TRUE;
  108. }
  109. /******************************************************************************/
  110. //
  111. void CImgToolWnd::OnSysColorChange()
  112. {
  113. CToolboxWnd::OnSysColorChange();
  114. InvalidateRect(NULL, FALSE);
  115. }
  116. /******************************************************************************/
  117. int CImgToolWnd::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
  118. {
  119. CRect rect;
  120. CTool* pTool = ToolFromPoint( &rect, &point );
  121. if (pTool != NULL)
  122. {
  123. int nHit = pTool->m_wID;
  124. if (pTI != NULL)
  125. {
  126. pTI->hwnd = m_hWnd;
  127. pTI->uId = nHit;
  128. pTI->rect = rect;
  129. pTI->lpszText = LPSTR_TEXTCALLBACK;
  130. }
  131. return nHit;
  132. }
  133. return -1; // not found
  134. }
  135. /******************************************************************************/
  136. void CImgToolWnd::OnUpdateCmdUI( CFrameWnd* pTarget, BOOL bDisableIfNoHndler )
  137. {
  138. }
  139. /******************************************************************************/
  140. CSize CImgToolWnd::CalcFixedLayout( BOOL bStretch, BOOL bHorz )
  141. {
  142. #ifdef TRYANYTHING
  143. return GetSize();
  144. #else
  145. CSize size = CControlBar::CalcFixedLayout( bStretch, bHorz );
  146. CSize sizeBar = GetSize();
  147. size.cx = sizeBar.cx;
  148. return size;
  149. #endif
  150. }
  151. /******************************************************************************/
  152. UINT CImgToolWnd::OnNcHitTest(CPoint point)
  153. {
  154. return CToolboxWnd::OnNcHitTest(point);
  155. }
  156. /******************************************************************************/
  157. CSize CImgToolWnd::GetSize()
  158. {
  159. // Leave room in the toolbox for the brushes...
  160. CRect clientRect;
  161. CRect windowRect;
  162. CSize sizeDiff;
  163. GetWindowRect( &windowRect );
  164. GetClientRect( &clientRect );
  165. sizeDiff = windowRect.Size() - clientRect.Size();
  166. int nTools = GetToolCount();
  167. clientRect.right = m_btnsize.x * NUM_TOOLS_WIDE + m_nOffsetX * 2;
  168. clientRect.bottom = (nTools / NUM_TOOLS_WIDE + (!!(nTools % NUM_TOOLS_WIDE)))
  169. * m_btnsize.y + m_nOffsetY * 2;
  170. m_rcTools.left = m_nOffsetX;
  171. m_rcTools.top = m_nOffsetY;
  172. m_rcTools.right = clientRect.right - m_nOffsetX;
  173. m_rcTools.bottom = clientRect.bottom - m_nOffsetY;
  174. m_rcBrushes.left = clientRect.left + (4 + m_nOffsetX);
  175. m_rcBrushes.top = clientRect.bottom;
  176. m_rcBrushes.right = clientRect.right - (4 + m_nOffsetX);
  177. m_rcBrushes.bottom = clientRect.bottom + 66;
  178. clientRect.bottom += m_rcBrushes.Height() + m_nOffsetY;
  179. return clientRect.Size() + sizeDiff;
  180. }
  181. /******************************************************************************/
  182. void CImgToolWnd::OnLButtonDown(UINT nFlags, CPoint pt)
  183. {
  184. BOOL bInBrushes = m_rcBrushes.PtInRect(pt);
  185. if (bInBrushes)
  186. {
  187. CRect optionsRect = m_rcBrushes;
  188. optionsRect.InflateRect(-1, -1);
  189. pt -= (CSize)optionsRect.TopLeft();
  190. CImgTool::GetCurrent()->OnClickOptions(this, optionsRect, pt);
  191. }
  192. else
  193. CToolboxWnd::OnLButtonDown(nFlags, pt);
  194. }
  195. /******************************************************************************/
  196. void CImgToolWnd::InvalidateOptions(BOOL bErase)
  197. {
  198. // NOTE: bErase is now ignored since we do drawing off-screen and
  199. // blt the whole thing...
  200. CRect optionsRect = m_rcBrushes;
  201. optionsRect.InflateRect(-1, -1);
  202. InvalidateRect(&optionsRect, FALSE);
  203. }
  204. /******************************************************************************/
  205. void CImgToolWnd::OnLButtonDblClk(UINT nFlags, CPoint pt)
  206. {
  207. CToolboxWnd::OnLButtonDblClk(nFlags, pt);
  208. }
  209. /******************************************************************************/
  210. void CImgToolWnd::OnRButtonDown(UINT nFlags, CPoint pt)
  211. {
  212. CToolboxWnd::OnRButtonDown(nFlags, pt);
  213. }
  214. /******************************************************************************/
  215. BOOL CImgToolWnd::OnEraseBkgnd( CDC* pDC )
  216. {
  217. CRect rect;
  218. GetClientRect( rect );
  219. pDC->FillRect( rect, GetSysBrush( COLOR_BTNFACE ) );
  220. return CControlBar::OnEraseBkgnd( pDC );
  221. }
  222. /******************************************************************************/
  223. void CImgToolWnd::OnPaint()
  224. {
  225. CPaintDC dc(this);
  226. if (dc.m_hDC == NULL)
  227. {
  228. theApp.SetGdiEmergency();
  229. return;
  230. }
  231. if (CImgWnd::c_pImgWndCur == NULL)
  232. {
  233. // Chances are, we're are going to be hidden soon, so don't
  234. // bother painting...
  235. return;
  236. }
  237. DrawButtons(dc, &dc.m_ps.rcPaint);
  238. ASSERT(CImgWnd::c_pImgWndCur->m_pImg != NULL);
  239. // Brush Shapes
  240. if (!(m_rcBrushes & dc.m_ps.rcPaint).IsRectEmpty())
  241. {
  242. Draw3dRect(dc.m_hDC, &m_rcBrushes );
  243. CRect optionsRect = m_rcBrushes;
  244. optionsRect.InflateRect(-1, -1);
  245. CRect rc(0, 0, optionsRect.Width(), optionsRect.Height());
  246. CDC memDC;
  247. CBitmap memBM;
  248. if (!memDC.CreateCompatibleDC(&dc) ||
  249. !memBM.CreateCompatibleBitmap(&dc, rc.right, rc.bottom))
  250. {
  251. theApp.SetGdiEmergency();
  252. return;
  253. }
  254. CBitmap* pOldBitmap = memDC.SelectObject(&memBM);
  255. CBrush* pOldBrush = memDC.SelectObject(GetSysBrush( COLOR_BTNFACE ));
  256. memDC.PatBlt(0, 0, rc.right, rc.bottom, PATCOPY);
  257. CRect rcPaint = dc.m_ps.rcPaint;
  258. rcPaint.OffsetRect(-optionsRect.left, -optionsRect.top);
  259. CImgTool::GetCurrent()->OnPaintOptions(&memDC, rcPaint, rc);
  260. dc.BitBlt(optionsRect.left, optionsRect.top, optionsRect.Width(),
  261. optionsRect.Height(), &memDC, 0, 0, SRCCOPY);
  262. memDC.SelectObject(pOldBitmap);
  263. memDC.SelectObject(pOldBrush);
  264. }
  265. }
  266. /******************************************************************************/
  267. BOOL CImgToolWnd::PreTranslateMessage(MSG* pMsg)
  268. {
  269. switch (pMsg->message)
  270. {
  271. case WM_KEYDOWN:
  272. case WM_KEYUP:
  273. case WM_CHAR:
  274. if (CImgWnd::c_pImgWndCur != NULL)
  275. {
  276. pMsg->hwnd = CImgWnd::c_pImgWndCur->m_hWnd;
  277. return CImgWnd::c_pImgWndCur->PreTranslateMessage(pMsg);
  278. }
  279. return FALSE;
  280. }
  281. return CToolboxWnd::PreTranslateMessage(pMsg);
  282. }
  283. /******************************************************************************/
  284. // default button size
  285. const POINT NEAR CToolboxWnd::ptDefButton = { 26, 26 };
  286. /*DK*/
  287. BEGIN_MESSAGE_MAP(CToolboxWnd, CControlBar)
  288. ON_WM_SYSCOLORCHANGE()
  289. ON_WM_PAINT()
  290. ON_WM_LBUTTONDOWN()
  291. ON_WM_RBUTTONDOWN()
  292. ON_WM_LBUTTONDBLCLK()
  293. ON_WM_MOUSEMOVE()
  294. ON_WM_LBUTTONUP()
  295. ON_WM_CLOSE()
  296. ON_WM_DESTROY()
  297. ON_WM_WININICHANGE()
  298. ON_WM_KEYDOWN()
  299. ON_MESSAGE(TM_TOOLDOWN, OnToolDown)
  300. ON_MESSAGE(TM_TOOLUP, OnToolUp)
  301. ON_MESSAGE(WM_THEMECHANGED, OnThemeChanged)
  302. /*DK*/
  303. // ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)
  304. END_MESSAGE_MAP()
  305. /******************************************************************************/
  306. CToolboxWnd::CToolboxWnd()
  307. {
  308. m_Tools = new CObArray;
  309. m_bmStuck = NULL;
  310. m_bmPushed = NULL;
  311. m_bmPopped = NULL;
  312. m_tCapture = NULL;
  313. m_bInside = FALSE;
  314. m_nOffsetX = 0;
  315. m_nOffsetY = 0;
  316. m_pLastHot = 0;
  317. m_hTheme = 0;
  318. }
  319. /******************************************************************************/
  320. CToolboxWnd::~CToolboxWnd()
  321. {
  322. if (m_bmStuck != NULL)
  323. delete m_bmStuck;
  324. if (m_bmPushed != NULL)
  325. delete m_bmPushed;
  326. if (m_bmPopped != NULL)
  327. delete m_bmPopped;
  328. if (m_Tools != NULL)
  329. {
  330. int nTools = (int)m_Tools->GetSize();
  331. for (int iTool = 0; iTool < nTools; iTool += 1)
  332. {
  333. CTool* pTool = (CTool*)m_Tools->GetAt(iTool);
  334. delete pTool;
  335. }
  336. delete m_Tools;
  337. }
  338. }
  339. /******************************************************************************/
  340. BOOL CToolboxWnd::Create(const TCHAR FAR* lpWindowName,
  341. DWORD dwStyle, const RECT& rect,
  342. const POINT& btnsize /* = ptDefButton */, WORD wWide /* = 1 */,
  343. CWnd* pParentWnd /* = NULL */, int nImageWellID /* = 0 */)
  344. {
  345. // This routine is a lot more complicated than the typical Create, so
  346. // because (1) we aren't a built-in Windows window type, and (2) we
  347. // want to specify the client size with the btnsize and wWide parameters.
  348. // (We ignore the width, height of the rect parameter.)
  349. if (nImageWellID != 0 && !m_imageWell.Load(nImageWellID, CSize(16, 16)))
  350. return FALSE;
  351. // save the style
  352. m_dwStyle = (UINT)dwStyle | CBRS_TOOLTIPS | CBRS_FLYBY;
  353. DWORD dwS = (m_dwStyle & ~WS_VISIBLE);
  354. CRect t = rect;
  355. t.right = t.left + 20;
  356. t.bottom = t.top + 20;
  357. BOOL bRet = CControlBar::Create( NULL, lpWindowName, dwS, t, pParentWnd,
  358. ID_VIEW_TOOL_BOX );
  359. if (! bRet)
  360. return FALSE;
  361. m_wWide = wWide;
  362. m_btnsize = btnsize;
  363. #ifdef TRYANYTHING
  364. SizeByButtons( -1, TRUE );
  365. #else
  366. SizeByButtons( 0 );
  367. #endif
  368. m_hTheme = SafeOpenThemeData(GetSafeHwnd(), L"toolbar");
  369. if (! DrawStockBitmaps())
  370. {
  371. DestroyWindow();
  372. return FALSE;
  373. }
  374. if (dwStyle & WS_VISIBLE)
  375. {
  376. ShowWindow(SW_SHOW);
  377. UpdateWindow();
  378. }
  379. return TRUE;
  380. }
  381. /******************************************************************************/
  382. // private DrawStockBitmaps:
  383. // Draws the three states of button, given the desired button size of this
  384. // CToolboxWnd. These have no graphic on them; the buttons have bitmap
  385. // glyphs to be added to these blank forms.
  386. //
  387. // The three states:
  388. // m_bmPopped This is the normal look of a button. Note that this is
  389. // also used as the basis of a grayed (disabled) button, by
  390. // changing how the button's glyph is drawn on it.
  391. // m_bmPushed This is the button-down state for non-sticky tools (tools
  392. // that pop back out as soon as you let go.
  393. // m_bmStuck This is the button-down state for sticky tools. This has
  394. // a distinct look that is more easily visible, per UISG.
  395. //
  396. BOOL CToolboxWnd::DrawStockBitmaps()
  397. {
  398. CWindowDC wdc(this);
  399. if (wdc.m_hDC == NULL)
  400. {
  401. theApp.SetGdiEmergency(TRUE);
  402. return FALSE;
  403. }
  404. CBitmap* obm;
  405. CBrush* obr;
  406. CRect rc;
  407. CDC dc;
  408. if (!dc.CreateCompatibleDC(&wdc))
  409. {
  410. theApp.SetGdiEmergency(TRUE);
  411. return FALSE;
  412. }
  413. obr = dc.SelectObject(GetSysBrush(COLOR_WINDOWFRAME));
  414. // bmPopped:
  415. //
  416. if (m_bmPopped)
  417. delete m_bmPopped;
  418. m_bmPopped = new CBitmap;
  419. if (!m_bmPopped->CreateCompatibleBitmap(&wdc, m_btnsize.x, m_btnsize.y))
  420. {
  421. theApp.SetMemoryEmergency(TRUE);
  422. return FALSE;
  423. }
  424. obm = dc.SelectObject(m_bmPopped);
  425. rc = CRect(0, 0, m_btnsize.x, m_btnsize.y);
  426. BPR(GetSysBrush(COLOR_WINDOWFRAME), PATCOPY);
  427. #ifdef OLDBUTTONS
  428. rc.right--; rc.bottom--;
  429. BPR(GetSysBrush(COLOR_BTNSHADOW), PATCOPY);
  430. #endif
  431. rc.right--; rc.bottom--;
  432. BPR(GetSysBrush(COLOR_BTNHIGHLIGHT), PATCOPY);
  433. rc.left++; rc.top++;
  434. BPR(GetSysBrush(COLOR_BTNSHADOW), PATCOPY);
  435. rc.right--; rc.bottom--;
  436. BPR(GetSysBrush(COLOR_BTNFACE), PATCOPY);
  437. // bmPushed:
  438. //
  439. if (m_bmPushed)
  440. delete m_bmPushed;
  441. m_bmPushed = new CBitmap;
  442. if (!m_bmPushed->CreateCompatibleBitmap(&wdc, m_btnsize.x, m_btnsize.y))
  443. {
  444. theApp.SetMemoryEmergency(TRUE);
  445. return FALSE;
  446. }
  447. dc.SelectObject(m_bmPushed);
  448. rc = CRect(0, 0, m_btnsize.x, m_btnsize.y);
  449. #ifndef OLDBUTTONS
  450. BPR(GetSysBrush(COLOR_BTNHIGHLIGHT), PATCOPY);
  451. rc.right--; rc.bottom--;
  452. BPR(GetSysBrush(COLOR_WINDOWFRAME), PATCOPY);
  453. rc.left++; rc.top++;
  454. BPR(GetSysBrush(COLOR_BTNFACE), PATCOPY);
  455. rc.right--; rc.bottom--;
  456. BPR(GetSysBrush(COLOR_BTNSHADOW), PATCOPY);
  457. rc.left++; rc.top++;
  458. BPR(GetSysBrush(COLOR_BTNFACE), PATCOPY);
  459. #else
  460. BPR(GetSysBrush(COLOR_WINDOWFRAME), PATCOPY);
  461. rc.right--; rc.bottom--;
  462. BPR(GetSysBrush(COLOR_BTNSHADOW), PATCOPY);
  463. rc.left += 2; rc.top += 2;
  464. BPR(GetSysBrush(COLOR_BTNFACE), PATCOPY);
  465. #endif
  466. // bmStuck:
  467. //
  468. if (m_bmStuck)
  469. delete m_bmStuck;
  470. m_bmStuck = new CBitmap;
  471. if (!m_bmStuck->CreateCompatibleBitmap(&wdc, m_btnsize.x, m_btnsize.y))
  472. {
  473. theApp.SetMemoryEmergency(TRUE);
  474. return FALSE;
  475. }
  476. dc.SelectObject(m_bmStuck);
  477. rc = CRect(0, 0, m_btnsize.x, m_btnsize.y);
  478. #ifndef OLDBUTTONS
  479. BPR(GetSysBrush(COLOR_BTNHIGHLIGHT), PATCOPY);
  480. rc.right--; rc.bottom--;
  481. BPR(GetSysBrush(COLOR_WINDOWFRAME), PATCOPY);
  482. rc.left++; rc.top++;
  483. BPR(GetSysBrush(COLOR_BTNFACE), PATCOPY);
  484. rc.right--; rc.bottom--;
  485. BPR(GetSysBrush(COLOR_BTNSHADOW), PATCOPY);
  486. rc.left++; rc.top++;
  487. #else
  488. BPR(GetSysBrush(COLOR_WINDOWFRAME), PATCOPY);
  489. rc.right--; rc.bottom--;
  490. BPR(GetSysBrush(COLOR_BTNSHADOW), PATCOPY);
  491. rc.left += 2; rc.top += 2;
  492. #endif
  493. dc.SelectObject(GetHalftoneBrush());
  494. #ifdef OLDBUTTONS
  495. dc.SetTextColor(RGB(255, 255, 255));
  496. dc.SetBkColor(RGB(192, 192, 192));
  497. #else
  498. dc.SetTextColor(GetSysColor(COLOR_BTNFACE));
  499. dc.SetBkColor(GetSysColor(COLOR_BTNHIGHLIGHT));
  500. #endif
  501. dc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATCOPY);
  502. dc.SelectObject(obm);
  503. dc.SelectObject(obr);
  504. dc.DeleteDC();
  505. return TRUE;
  506. }
  507. /******************************************************************************/
  508. //
  509. afx_msg void CToolboxWnd::OnSysColorChange()
  510. {
  511. CControlBar::OnSysColorChange();
  512. DrawStockBitmaps();
  513. InvalidateRect(NULL, FALSE);
  514. }
  515. /******************************************************************************/
  516. //
  517. // SizeByButtons
  518. //
  519. // Sizes the window according to the current (or a specified) number of
  520. // buttons. If there are no buttons, the window makes room for one button.
  521. // Unfilled button slots show through to the background.
  522. //
  523. void CToolboxWnd::SizeByButtons(int nButtons /* = -1 */,
  524. BOOL bRepaint /* = FALSE */)
  525. {
  526. if (nButtons == -1)
  527. nButtons = (int)m_Tools->GetSize();
  528. if (nButtons == 0)
  529. nButtons = 1;
  530. // Can't use the hokey Windows' AdjustWindowRect() to work this out,
  531. // so we do it ourselves by adapting the window based on the difference
  532. // between GetWindowRect and ClientRect results.
  533. //
  534. CRect w, c;
  535. GetWindowRect(&w);
  536. w.right -= w.left;
  537. w.bottom -= w.top;
  538. GetClientRect(&c);
  539. if (bRepaint)
  540. Invalidate(TRUE);
  541. MoveWindow(w.left, w.top,
  542. m_btnsize.x * m_wWide + (w.right - c.right) - 1,
  543. m_btnsize.y * ((nButtons / m_wWide) + (!!(nButtons % m_wWide)))
  544. + (w.bottom-c.bottom) - 1,
  545. bRepaint);
  546. }
  547. /******************************************************************************/
  548. // OnWinIniChange:
  549. //
  550. void CToolboxWnd::OnWinIniChange(LPCTSTR lpSection)
  551. {
  552. lpSection;
  553. #ifdef TRYANYTHING
  554. CControlBar::OnWinIniChange( lpSection );
  555. #endif
  556. DrawStockBitmaps();
  557. Invalidate(TRUE);
  558. }
  559. /******************************************************************************/
  560. //
  561. // OnKeyDown
  562. //
  563. // Implements keyboard handling for the toolbox window.. this allows
  564. // trapping of the ESC key, for moving the selected to back to the
  565. // arrow.
  566. //
  567. void CToolboxWnd::OnKeyDown(UINT nKey, UINT nRepCnt, UINT nFlags)
  568. {
  569. if (nKey == VK_ESCAPE && m_tCapture)
  570. CancelDrag();
  571. else
  572. CControlBar::OnKeyDown(nKey, nRepCnt, nFlags);
  573. }
  574. /******************************************************************************/
  575. void CToolboxWnd::CancelDrag()
  576. {
  577. #if 0
  578. // this is bogus as dragging is presently disabled
  579. if (m_tCapture != NULL)
  580. m_tCapture->m_wState |= TF_DRAG; // so select will cancel it
  581. #endif
  582. m_bInside = FALSE;
  583. #if 0
  584. // whoever tries to make drag/drop work will have to handle the fact
  585. // that our client does not get notified by SelectTool
  586. SelectTool( IDMB_ARROW );
  587. #endif
  588. m_tCapture = NULL;
  589. ReleaseCapture();
  590. }
  591. /******************************************************************************/
  592. // AddTool:
  593. //
  594. void CToolboxWnd::AddTool(CTool* tool)
  595. {
  596. m_Tools->Add((CObject*)tool);
  597. if ((m_Tools->GetSize() + m_wWide - 1) / m_wWide > 11) // only have 11 high if more increase the width
  598. m_wWide += 1;
  599. SizeByButtons(-1, TRUE);
  600. }
  601. /******************************************************************************/
  602. // RemoveTool:
  603. //
  604. void CToolboxWnd::RemoveTool(CTool* tool)
  605. {
  606. for (int nTool = GetToolCount() - 1; GetToolAt(nTool) != tool; nTool -= 1)
  607. ASSERT(nTool >= 0);
  608. m_Tools->RemoveAt(nTool);
  609. if ((m_Tools->GetSize() + m_wWide - 2) / (m_wWide - 1) <= 11 && m_wWide > 1)
  610. m_wWide -= 1;
  611. SizeByButtons(-1, TRUE);
  612. }
  613. /******************************************************************************/
  614. // private GetTool:
  615. //
  616. CTool* CToolboxWnd::GetTool(WORD wID)
  617. {
  618. int nTools = (int)m_Tools->GetSize();
  619. for (int i = 0; i < nTools; i++)
  620. {
  621. CTool* t = (CTool*)m_Tools->GetAt(i);
  622. if (t && t->m_wID == wID)
  623. return t;
  624. }
  625. return NULL;
  626. }
  627. /******************************************************************************/
  628. //
  629. // SetToolState
  630. //
  631. // Used by the owner of a button to modify the state of the button.
  632. // This does not notify the owner of the new state; presumably the
  633. // owner knows what it's doing to its own buttons. This allows the
  634. // owner to use this API during a WM_TOOLDOWN, etc., without getting
  635. // into a shouting match with the toolbox.
  636. //
  637. WORD CToolboxWnd::SetToolState(WORD wID, WORD wState)
  638. {
  639. CRect rect;
  640. CTool* t = GetTool(wID);
  641. if (t && !(t->m_wState & TF_NYI))
  642. {
  643. WORD w = t->m_wState;
  644. t->m_wState = wState;
  645. //
  646. // if state hasn't changed, return to avoid invalidate and
  647. // associated flicker.
  648. //
  649. if (w == wState)
  650. return w;
  651. //
  652. // Calculate the rectangle of the button whose state is changing,
  653. // and invalidate it.
  654. //
  655. // replaces ed's simplistic (and flickering) code:
  656. //
  657. // Invalidate(FALSE)
  658. //
  659. for (int i = 0; (CTool*)m_Tools->GetAt(i) != t; i += 1)
  660. {
  661. ASSERT(i != m_Tools->GetSize());
  662. }
  663. rect.left = (i % m_wWide) * m_btnsize.x + m_nOffsetX;
  664. rect.top = (i / m_wWide) * m_btnsize.y + m_nOffsetY;
  665. rect.right = rect.left + m_btnsize.x;
  666. rect.bottom = rect.top + m_btnsize.y;
  667. InvalidateRect(&rect, TRUE);
  668. return w;
  669. }
  670. return 0;
  671. }
  672. /******************************************************************************/
  673. // SetToolStyle:
  674. // Used by the owner of a button to modify the style of the button.
  675. // This forces the state of the button to be enabled and released.
  676. // This does not notify the owner of the new state; presumably the
  677. // owner knows what it's doing to its own buttons. This allows the
  678. // owner to use this API during a WM_TOOLDOWN, etc., without getting
  679. // into a shouting match with the toolbox.
  680. //
  681. WORD CToolboxWnd::SetToolStyle(WORD wID, WORD wStyle)
  682. {
  683. CTool* t = GetTool(wID);
  684. if (t)
  685. {
  686. WORD w = t->m_wStyle;
  687. t->m_wStyle = wStyle;
  688. t->m_wState = 0;
  689. Invalidate(FALSE);
  690. return w;
  691. }
  692. return 0;
  693. }
  694. /******************************************************************************/
  695. //
  696. // SelectTool
  697. //
  698. // Selects a given tool and deselects all the other tools. So, for instance,
  699. // to select the arrow, call pToolbox->SelectTool(IDMB_ARROW);
  700. //
  701. void CToolboxWnd::SelectTool(WORD wID)
  702. {
  703. //
  704. // first clear all the tools except the one we want pressed, then
  705. // select the one we want.
  706. //
  707. for (int i = 0; i < m_Tools->GetSize(); i += 1)
  708. {
  709. CTool* pTool = (CTool*)m_Tools->GetAt(i);
  710. if (pTool->m_wID != wID)
  711. SetToolState(pTool->m_wID, 0);
  712. }
  713. SetToolState( wID, TF_SELECTED );
  714. }
  715. /******************************************************************************/
  716. /* CToolboxWnd::CurrentTool
  717. *
  718. * Returns the ID of the currently selected tool.
  719. */
  720. WORD CToolboxWnd::CurrentToolID()
  721. {
  722. int nTools = (int)m_Tools->GetSize();
  723. for (int i = 0; i < nTools; i++)
  724. {
  725. CTool* t = (CTool*)m_Tools->GetAt(i);
  726. if (t && t->m_wState == TF_SELECTED)
  727. return t->m_wID;
  728. }
  729. return IDMB_ARROW;
  730. }
  731. /******************************************************************************/
  732. #define HITTYPE_SUCCESS 0 // hit an item in the control bar
  733. #define HITTYPE_NOTHING (-1) // hit nothing, but hit the control bar itself
  734. #define HITTYPE_OUTSIDE (-2) // hit a window outside of the control bar
  735. #define HITTYPE_TRACKING (-3) // this app is has the focus (is tracking)
  736. #define HITTYPE_INACTIVE (-4) // the app is not active
  737. #define HITTYPE_DISABLED (-5) // the control bar is disabled
  738. #define HITTYPE_FOCUS (-6) // the control bar has focus
  739. int CToolboxWnd::HitTestToolTip( CPoint point, UINT* pHit )
  740. {
  741. if (pHit)
  742. *pHit = (UINT)-1; // assume it won't hit anything
  743. int iReturn = HITTYPE_INACTIVE;
  744. // make sure this app is active
  745. if (theApp.m_bActiveApp)
  746. {
  747. // check for this application tracking (capture set)
  748. if (! m_tCapture)
  749. {
  750. // finally do the hit test on the items within the control bar
  751. ScreenToClient( &point );
  752. CRect rect;
  753. CTool* pTool = ToolFromPoint( &rect, &point );
  754. if (pTool && rect.PtInRect( point ))
  755. {
  756. iReturn = HITTYPE_SUCCESS;
  757. if (pHit)
  758. *pHit = pTool->m_wID;
  759. }
  760. else
  761. iReturn = HITTYPE_OUTSIDE;
  762. }
  763. else
  764. iReturn = HITTYPE_TRACKING;
  765. }
  766. #ifdef _DEBUG
  767. TRACE2( "HitTestToolType %d - %u\n", iReturn, pHit );
  768. #endif
  769. return iReturn;
  770. }
  771. /******************************************************************************/
  772. UINT CToolboxWnd::OnCmdHitTest( CPoint point, CPoint* pCenter )
  773. {
  774. ASSERT_VALID( this );
  775. // now hit test against CToolBar buttons
  776. CRect rect;
  777. UINT nHit = (UINT)-1;
  778. CTool* pTool = ToolFromPoint( &rect, &point );
  779. if (pTool)
  780. nHit = pTool->m_wID;
  781. return nHit;
  782. }
  783. /******************************************************************************/
  784. // private ToolFromPoint:
  785. // Given a CPoint in client coordinates, this function returns the tool
  786. // associated with the button at that point, if any. If a tool is found,
  787. // the given CRect (if not NULL) is filled with the bounds of the tool's
  788. // button.
  789. //
  790. CTool* CToolboxWnd::ToolFromPoint(CRect* rect, CPoint* pt) const
  791. {
  792. CRect c = m_rcTools;
  793. CPoint p = *pt;
  794. if (p.x < c.left || p.x >= c.right
  795. || p.y < c.top || p.y >= c.bottom)
  796. return NULL;
  797. int x = (p.x - m_nOffsetX) / m_btnsize.x;
  798. int y = (p.y - m_nOffsetY) / m_btnsize.y;
  799. int i = x + (y * m_wWide);
  800. if (i >= m_Tools->GetSize())
  801. return NULL;
  802. CTool* t = (CTool*)(m_Tools->GetAt( i ));
  803. if (t && rect)
  804. {
  805. rect->left = m_btnsize.x * x + m_nOffsetX;
  806. rect->top = m_btnsize.y * y + m_nOffsetY;
  807. rect->right = rect->left + m_btnsize.x;
  808. rect->bottom = rect->top + m_btnsize.y;
  809. }
  810. return t;
  811. }
  812. /******************************************************************************/
  813. // OnLButtonDown:
  814. void CToolboxWnd::OnLButtonDown(UINT wFlags, CPoint point)
  815. {
  816. wFlags; // Avoid unused arg warnings
  817. m_tCapture = ToolFromPoint( &m_lasttool, &point );
  818. m_downpt = point;
  819. if (m_tCapture)
  820. {
  821. CRect rect = m_lasttool;
  822. CString strPrompt;
  823. m_bInside = FALSE;
  824. rect.InflateRect( -1, -1 );
  825. if (rect.PtInRect( point ))
  826. {
  827. if (m_tCapture->m_wID <= IDMB_USERBTN)
  828. GetOwner()->SendMessage( WM_SETMESSAGESTRING, (WPARAM)m_tCapture->m_wID );
  829. if (m_tCapture->m_wState & TF_DISABLED)
  830. m_tCapture = NULL;
  831. else
  832. m_bInside = TRUE;
  833. }
  834. else
  835. m_tCapture = NULL;
  836. }
  837. else
  838. {
  839. CControlBar::OnLButtonDown(wFlags,point);
  840. }
  841. if (m_tCapture )
  842. {
  843. SetCapture();
  844. if (m_tCapture)
  845. InvalidateRect( &m_lasttool, TRUE );
  846. }
  847. }
  848. /******************************************************************************/
  849. void CToolboxWnd::OnRButtonDown(UINT wFlags, CPoint point)
  850. {
  851. wFlags;
  852. point;
  853. if (GetCapture() == this)
  854. CancelDrag();
  855. }
  856. /******************************************************************************/
  857. /*DK*/
  858. // LRESULT CToolboxWnd::OnHelpHitTest(WPARAM wParam, LPARAM lParam)
  859. // {
  860. // CPoint pt(lParam);
  861. // CTool* t = ToolFromPoint(&m_lasttool, &pt);
  862. //
  863. // if (t == NULL)
  864. // return CMiniFrmWnd::OnHelpHitTest(wParam, lParam);
  865. // else
  866. // {
  867. // ASSERT( t->m_wID );
  868. // return HID_BASE_BUTTON + t->m_wID;
  869. // }
  870. // }
  871. // OnLButtonDblClk: FUTURE: Maybe just not use CS_DBLCLKS?
  872. //
  873. void CToolboxWnd::OnLButtonDblClk(UINT wFlags, CPoint point)
  874. {
  875. OnLButtonDown(wFlags, point);
  876. }
  877. /******************************************************************************/
  878. BOOL CToolboxWnd::SetStatusText(int nHit)
  879. {
  880. if (nHit == -1 && m_pLastHot != 0)
  881. {
  882. m_pLastHot->m_wState &= ~TF_HOT;
  883. InvalidateRect(&m_rectLastHot, TRUE);
  884. m_pLastHot = 0;
  885. }
  886. return CControlBar::SetStatusText(nHit);
  887. }
  888. /******************************************************************************/
  889. // OnMouseMove:
  890. //
  891. void CToolboxWnd::OnMouseMove(UINT wFlags, CPoint point)
  892. {
  893. CTool* t = m_tCapture;
  894. if (! t || (t->m_wState & TF_DISABLED))
  895. {
  896. if (m_hTheme)
  897. {
  898. CRect rectHot;
  899. CTool* pHot = ToolFromPoint(&rectHot, &point);
  900. if (m_pLastHot != pHot)
  901. {
  902. if (m_pLastHot)
  903. {
  904. m_pLastHot->m_wState &= ~TF_HOT;
  905. InvalidateRect(&m_rectLastHot, TRUE);
  906. }
  907. if (pHot)
  908. {
  909. pHot->m_wState |= TF_HOT;
  910. InvalidateRect(&rectHot, TRUE);
  911. }
  912. m_rectLastHot = rectHot;
  913. m_pLastHot = pHot;
  914. }
  915. }
  916. CControlBar::OnMouseMove( wFlags, point );
  917. return;
  918. }
  919. BOOL bWasInside = m_bInside;
  920. CRect rect = m_lasttool;
  921. rect.InflateRect( -1, -1 );
  922. m_bInside = ((! (t->m_wState & TF_DRAG)) && rect.PtInRect( point ));
  923. if (bWasInside != m_bInside)
  924. InvalidateRect( &m_lasttool, TRUE );
  925. if (t && !(t->m_wState & TF_DISABLED))
  926. {
  927. // if it's a mousemove and we're draggable, then see how far it
  928. // is from the original mousedown -- if it's a fair distance,
  929. // then drag it.
  930. if ((t->m_wStyle & TS_DRAG) &&
  931. (((point.x - m_downpt.x) > 3) ||
  932. ((point.y - m_downpt.y) > 3) ||
  933. ((m_downpt.x - point.x) > 3) ||
  934. ((m_downpt.y - point.y) > 3)))
  935. {
  936. t->m_wState |= TF_DRAG;
  937. if (t->m_wStyle & TS_STICKY)
  938. {
  939. if (!(t->m_wState & TF_SELECTED))
  940. {
  941. t->m_wState |= TF_SELECTED;
  942. if (t->m_pOwner)
  943. t->m_pOwner->SendMessage(TM_TOOLDOWN, t->m_wID);
  944. }
  945. if (m_bInside)
  946. InvalidateRect(&m_lasttool, TRUE);
  947. m_bInside = FALSE; // looks stuck immediately!
  948. }
  949. }
  950. if (t->m_pOwner && (t->m_wState & TF_DRAG))
  951. {
  952. CPoint spt = point;
  953. ClientToScreen(&spt);
  954. // if the drag and drop began ok, release the captured tool
  955. // if (t->m_pOwner->BeginDragDrop( t, spt ))
  956. // m_tCapture = NULL;
  957. }
  958. }
  959. }
  960. /******************************************************************************/
  961. // OnLButtonUp:
  962. void CToolboxWnd::OnLButtonUp(UINT wFlags, CPoint point)
  963. {
  964. if (! m_tCapture )
  965. {
  966. CControlBar::OnLButtonUp( wFlags, point );
  967. return;
  968. }
  969. CTool* t = m_tCapture;
  970. if (t && ! (t->m_wState & TF_DISABLED))
  971. {
  972. m_bInside = (point.x >= m_lasttool.left
  973. && point.x < m_lasttool.right
  974. && point.y >= m_lasttool.top
  975. && point.y < m_lasttool.bottom);
  976. if (m_bInside)
  977. {
  978. if (t->m_wStyle & TS_STICKY)
  979. {
  980. if (! (t->m_wState & TF_DRAG))
  981. {
  982. t->m_wState ^= TF_SELECTED;
  983. InvalidateRect(&m_lasttool, TRUE);
  984. if (t->m_pOwner)
  985. t->m_pOwner->SendMessage( t->m_wState & TF_SELECTED?
  986. TM_TOOLDOWN : TM_TOOLUP, t->m_wID );
  987. }
  988. }
  989. if (t->m_wStyle & TS_CMD)
  990. {
  991. if (t->m_pOwner)
  992. AfxGetMainWnd()->SendMessage( WM_COMMAND, t->m_wID );
  993. }
  994. }
  995. }
  996. ReleaseCapture();
  997. m_tCapture = NULL;
  998. m_bInside = FALSE;
  999. }
  1000. /******************************************************************************/
  1001. BOOL CToolboxWnd::OnCommand(UINT wParam, LONG lParam)
  1002. {
  1003. AfxGetMainWnd()->SendMessage(WM_COMMAND, wParam, lParam);
  1004. return TRUE;
  1005. }
  1006. /******************************************************************************/
  1007. void CToolboxWnd::DrawButtons(CDC& dc, RECT* rcPaint)
  1008. {
  1009. CRect rect;
  1010. CRect updateRect;
  1011. int i, n;
  1012. if (rcPaint == NULL)
  1013. {
  1014. GetClientRect( &updateRect );
  1015. rcPaint = &updateRect;
  1016. }
  1017. CDC memdc;
  1018. memdc.CreateCompatibleDC(&dc);
  1019. if (m_hTheme == 0)
  1020. {
  1021. // Force the buttons to be rebuilt here
  1022. DrawStockBitmaps();
  1023. }
  1024. CBitmap* obm = memdc.SelectObject( m_bmPopped );
  1025. CBrush* obr = memdc.SelectObject( GetSysBrush( COLOR_BTNTEXT ) );
  1026. n = (int)m_Tools->GetSize();
  1027. BOOL bUsedImageWell = FALSE;
  1028. for (i = 0; i < n; i++)
  1029. {
  1030. CTool* t = (CTool*)m_Tools->GetAt(i);
  1031. if (! t)
  1032. continue;
  1033. rect.left = (i % m_wWide) * m_btnsize.x + m_nOffsetX;
  1034. rect.top = (i / m_wWide) * m_btnsize.y + m_nOffsetY;
  1035. rect.right = rect.left + m_btnsize.x;
  1036. rect.bottom = rect.top + m_btnsize.y;
  1037. CRect ir;
  1038. if (! ir.IntersectRect( rcPaint, &rect ))
  1039. continue;
  1040. // Select the right stock bitmap, and remember to
  1041. // shove the graphic if it's in a pushed state.
  1042. //
  1043. CBitmap* bmStock = m_bmPopped;
  1044. int xshove = 0, yshove = 0;
  1045. int iButtonStateId = TS_NORMAL;
  1046. if (t->m_wState & (TF_SELECTED | TF_DRAG))
  1047. {
  1048. bmStock = m_bmStuck;
  1049. xshove = 1; yshove = 1;
  1050. iButtonStateId = t->m_wState & TF_HOT ? TS_HOTCHECKED : TS_CHECKED;
  1051. }
  1052. else if (t->m_wState & TF_HOT)
  1053. {
  1054. iButtonStateId = TS_HOT;
  1055. }
  1056. if ((t == m_tCapture && m_bInside) && !(t->m_wState & TF_DRAG))
  1057. {
  1058. bmStock = m_bmPushed;
  1059. xshove = 2; yshove = 2;
  1060. iButtonStateId = TS_PRESSED;
  1061. }
  1062. // Draw a blank button first...
  1063. if (m_hTheme)
  1064. {
  1065. DrawThemeBackground(m_hTheme, dc, TP_BUTTON, iButtonStateId, &rect, 0);
  1066. }
  1067. else
  1068. {
  1069. ::DrawBitmap(&dc, bmStock, &rect, SRCCOPY, &memdc);
  1070. }
  1071. // Now draw the glyph on top...
  1072. rect.OffsetRect( xshove, yshove );
  1073. if (! bUsedImageWell)
  1074. {
  1075. if (! m_imageWell.Open())
  1076. goto LReturn;
  1077. bUsedImageWell = TRUE;
  1078. if (! m_imageWell.CalculateMask())
  1079. goto LReturn;
  1080. }
  1081. CPoint pt( rect.left + (rect.Width() - 16) / 2,
  1082. rect.top + (rect.Height() - 16) / 2 );
  1083. m_imageWell.DrawImage( &dc, pt, t->m_nImage );
  1084. }
  1085. LReturn:
  1086. if (bUsedImageWell)
  1087. m_imageWell.Close();
  1088. memdc.SelectObject(obr);
  1089. memdc.SelectObject(obm);
  1090. memdc.DeleteDC();
  1091. }
  1092. /******************************************************************************/
  1093. // OnPaint:
  1094. //
  1095. void CToolboxWnd::OnPaint()
  1096. {
  1097. CPaintDC dc(this);
  1098. if (dc.m_hDC == NULL)
  1099. {
  1100. theApp.SetGdiEmergency();
  1101. return;
  1102. }
  1103. DrawButtons(dc, &dc.m_ps.rcPaint);
  1104. }
  1105. /******************************************************************************/
  1106. // OnClose
  1107. //
  1108. // A toolbox is usally created by the parent, and will be destroyed
  1109. // specifically by the parent upon leaving the app. When the user closes
  1110. // the toolbox, it is simply hidden. The parent can then reshow it without
  1111. // recreating it.
  1112. //
  1113. // This also changes the menu test to "show" rather than "hide"
  1114. void CToolboxWnd::OnClose()
  1115. {
  1116. #ifdef TRYANYTHING
  1117. CControlBar::OnClose();
  1118. #endif
  1119. // ShowWindow(SW_HIDE);
  1120. }
  1121. /******************************************************************************/
  1122. // OnDestroy
  1123. //
  1124. void CToolboxWnd::OnDestroy()
  1125. {
  1126. if (m_hTheme)
  1127. {
  1128. CloseThemeData(m_hTheme);
  1129. m_hTheme = 0;
  1130. }
  1131. CControlBar::OnDestroy();
  1132. }
  1133. /******************************************************************************/
  1134. // OnThemeChanged
  1135. //
  1136. LRESULT CToolboxWnd::OnThemeChanged(WPARAM, LPARAM)
  1137. {
  1138. if (m_hTheme)
  1139. {
  1140. CloseThemeData(m_hTheme);
  1141. }
  1142. m_hTheme = SafeOpenThemeData(GetSafeHwnd(), L"toolbar");
  1143. InvalidateRect(0, TRUE);
  1144. return TRUE;
  1145. }
  1146. /******************************************************************************/
  1147. // OnToolDown:
  1148. //
  1149. LONG CToolboxWnd::OnToolDown(UINT wID, LONG /* lParam */)
  1150. {
  1151. for (int i = 0; i < m_Tools->GetSize(); i += 1)
  1152. {
  1153. CTool* pTool = (CTool*)m_Tools->GetAt(i);
  1154. if (pTool->m_wID != wID)
  1155. SetToolState(pTool->m_wID, 0);
  1156. }
  1157. return (LONG)TRUE;
  1158. }
  1159. /******************************************************************************/
  1160. // OnToolUp:
  1161. //
  1162. LONG CToolboxWnd::OnToolUp(UINT /* wID */, LONG /* lParam */)
  1163. {
  1164. for (int i = 0; i < m_Tools->GetSize(); i += 1)
  1165. {
  1166. CTool* pTool = (CTool*)m_Tools->GetAt(i);
  1167. SetToolState(pTool->m_wID, 0);
  1168. }
  1169. SetToolState(IDMB_ARROW, TF_SELECTED);
  1170. return (LONG)TRUE;
  1171. }
  1172. #ifdef XYZZYZ
  1173. /******************************************************************************/
  1174. // OnSwitch:
  1175. //
  1176. LONG CToolboxWnd::OnSwitch(UINT /* wID */, LONG /* point */)
  1177. {
  1178. return (LONG)TRUE;
  1179. }
  1180. /******************************************************************************/
  1181. // OnQueryDrop:
  1182. //
  1183. BOOL CToolboxWnd::BeginDragDrop (CTool* /*pTool*/, CPoint /*pt*/)
  1184. {
  1185. return FALSE;
  1186. }
  1187. #endif
  1188. /******************************************************************************/
  1189. CTool::CTool(CToolboxWnd* pOwner, WORD wID, int nImage,
  1190. WORD wStyle /* = 0 */, WORD wState /* = 0 */)
  1191. {
  1192. m_pOwner = pOwner;
  1193. m_wID = wID;
  1194. m_nImage = nImage;
  1195. m_wStyle = wStyle;
  1196. m_wState = wState;
  1197. }
  1198. /******************************************************************************/