ColourPopup.cpp
上传用户:cn05999
上传日期:2020-06-29
资源大小:84k
文件大小:15k
源码类别:

Static控件

开发平台:

Visual C++

  1. // ColourPopup.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "CProgressCtrl.h"
  5. #include "ColourPopup.h"
  6. //#include "ColourPicker.h"
  7. #include "math.h"
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13. #define TEXT_BOX_VALUE -2 //定义用户文本显示的按钮坐标
  14. #define MAX_COLOURS 100 //定义颜色板中最多的颜色数
  15. /////////////////////////////////////////////////////////////////////////////
  16. // CColourPopup
  17. ColourTableEntry CColourPopup::m_crColours[]=
  18. {
  19. {RGB(0x00,0x00,0x00), _T("黑色") },
  20. {RGB(0xA5,0x2A,0x00), _T("棕色") },
  21. {RGB(0x00,0x40,0x40), _T("橄榄绿色") },
  22. {RGB(0x00,0x55,0x00), _T("暗绿色") },
  23. {RGB(0x00,0x00,0x5E), _T("深青色") },
  24. {RGB(0x00,0x00,0x8B), _T("深蓝色") },
  25. {RGB(0x4B,0x00,0x82), _T("深紫蓝色") },
  26. {RGB(0x28,0x28,0x28), _T("深灰色") },
  27. {RGB(0x8B,0x00,0x00), _T("深红色") },
  28. {RGB(0xFF,0x68,0x20), _T("桔红色") },
  29. {RGB(0x8B,0x8B,0x00), _T("深黄色") },
  30. {RGB(0x00,0x93,0x00), _T("绿色") },
  31. {RGB(0x38,0x8E,0x8E), _T("青色") },
  32. {RGB(0x00,0x00,0xFF), _T("蓝色") },
  33. {RGB(0x7B,0x7B,0xC0), _T("绿灰色") },
  34. {RGB(0x66,0x66,0x66), _T("灰色") },
  35. {RGB(0xFF,0x00,0x00), _T("红色") },
  36. {RGB(0xFF,0xAD,0x5B), _T("淡桔红色") },
  37. {RGB(0x32,0xCD,0x32), _T("浅绿色") },
  38. {RGB(0x3C,0xB3,0x71), _T("海蓝色") },
  39. {RGB(0x7F,0xFF,0xD4), _T("浅绿色") },
  40. {RGB(0x7D,0x9E,0xC0), _T("淡蓝色") },
  41. {RGB(0x80,0x00,0x80), _T("紫罗兰色") },
  42. {RGB(0x7F,0x7F,0x7F), _T("灰色") },
  43. {RGB(0xFF,0xC0,0xCB), _T("粉红色") },
  44. {RGB(0xFF,0xD7,0x00), _T("金色") },
  45. {RGB(0xFF,0xFF,0x00), _T("黄色") },
  46. {RGB(0x00,0xFF,0x00), _T("亮绿色") },
  47. {RGB(0x40,0xE0,0xD0), _T("绿松色") },
  48. {RGB(0xC0,0xFF,0xFF), _T("天蓝色") },
  49. {RGB(0x48,0x00,0x48), _T("梅红") },
  50. {RGB(0xC0,0xC0,0xC0), _T("淡灰色") },
  51. {RGB(0xFF,0xE4,0xE1), _T("玫瑰色") },
  52. {RGB(0xD2,0xB4,0x8C), _T("棕褐色") },
  53. {RGB(0xFF,0xFF,0xE0), _T("淡黄色") },
  54. {RGB(0x98,0xFB,0x98), _T("浅绿色") },
  55. {RGB(0xAF,0xEE,0xEE), _T("浅绿宝石色")},
  56. {RGB(0x68,0x83,0x8B), _T("浅蓝色") },
  57. {RGB(0xE6,0xE6,0xFA), _T("淡紫色") },
  58. {RGB(0xFF,0xFF,0xFF), _T("白色") },
  59. };
  60. CColourPopup::CColourPopup()
  61. {
  62. Initialize();
  63. }
  64. CColourPopup::~CColourPopup()
  65. {
  66. m_Font.DeleteObject();
  67. m_Palette.DeleteObject();
  68. }
  69. BEGIN_MESSAGE_MAP(CColourPopup, CWnd)
  70. //{{AFX_MSG_MAP(CColourPopup)
  71. ON_WM_PAINT()
  72. ON_WM_LBUTTONUP()
  73. ON_WM_MOUSEMOVE()
  74. ON_WM_KEYDOWN()
  75. ON_WM_PALETTECHANGED()
  76. ON_WM_QUERYNEWPALETTE()
  77. ON_WM_NCDESTROY()
  78. //}}AFX_MSG_MAP
  79. END_MESSAGE_MAP()
  80. /////////////////////////////////////////////////////////////////////////////
  81. // CColourPopup message handlers
  82. void CColourPopup::Initialize()
  83. {
  84. m_nNumColours =sizeof(m_crColours)/sizeof(ColourTableEntry);
  85. ASSERT(m_nNumColours<=MAX_COLOURS);
  86. if(m_nNumColours>MAX_COLOURS)
  87. m_nNumColours=MAX_COLOURS;
  88. m_nNumColumns=0;
  89. m_nNumRows=0;
  90. m_nBoxSize=18;
  91. m_nMargin=::GetSystemMetrics(SM_CXEDGE);
  92. m_nCurrentRow=-1;
  93. m_nCurrentCol=-1;
  94. m_nChosenColourRow=-1;
  95. m_nChosenColourCol=-1;;
  96. m_bShowCustom=TRUE;
  97. m_strCustomText=_T("其它颜色");
  98. m_crInitialColour=m_crColour=RGB(0,0,0);
  99. m_pParent=NULL;
  100. if(m_nBoxSize-2*m_nMargin-2<5) m_nBoxSize=5+2*m_nMargin+2;
  101. //在颜色板中使用非客户区的字体
  102. //以下代码创建NONCLIENTMETRICS结构,
  103. NONCLIENTMETRICS ncm;
  104. ncm.cbSize=sizeof(NONCLIENTMETRICS);
  105. VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(NONCLIENTMETRICS),&ncm,0));
  106. m_Font.CreateFontIndirect(&(ncm.lfMessageFont));
  107. //创建 应用颜色板结构
  108. struct 
  109. {
  110. //逻辑颜色板
  111. LOGPALETTE Logpalette;
  112. PALETTEENTRY PalEntry[MAX_COLOURS];
  113. }pal;
  114. //颜色板的入口数为定义的颜色数
  115. LOGPALETTE* pLogPalette=(LOGPALETTE*)&pal;
  116. pLogPalette->palNumEntries=m_nNumColours;
  117. for(int i=0;i<m_nNumColours;i++)
  118. {
  119. pLogPalette->palPalEntry[i].peRed=GetRValue(m_crColours[i].crColour);
  120. pLogPalette->palPalEntry[i].peGreen=GetGValue(m_crColours[i].crColour);
  121. pLogPalette->palPalEntry[i].peBlue=GetBValue(m_crColours[i].crColour);
  122. pLogPalette->palPalEntry[i].peFlags=0;
  123. }
  124. //
  125. //以创建的逻辑板为模板来生成MFC的CPalette类
  126. m_Palette.CreatePalette(pLogPalette);
  127. }
  128. CColourPopup::CColourPopup(CPoint p, COLORREF crColour, CWnd *pParentWnd, UINT nID, LPCTSTR szCustomText/*=NULL*/)
  129. {
  130. Initialize();
  131. m_crColour=m_crInitialColour=crColour;
  132. if(szCustomText!=NULL)
  133. {
  134. m_bShowCustom=TRUE;
  135. m_strCustomText=szCustomText;
  136. }
  137. else
  138. m_bShowCustom=FALSE;
  139. m_pParent=pParentWnd;
  140. CColourPopup::Create(p,crColour,pParentWnd,nID,szCustomText);
  141. }
  142. BOOL CColourPopup::Create(CPoint p, COLORREF crColour, CWnd *pParentWnd, UINT nID, LPCTSTR szCustomText)
  143. {
  144. ASSERT(pParentWnd&&::IsWindow(pParentWnd->GetSafeHwnd()));
  145. // ASSERT(pParentWnd->IsKindOf(RUNTIME_CLASS(CColourPicker)));
  146. m_pParent=pParentWnd;
  147. m_crColour=m_crInitialColour=crColour;
  148. //创建 窗体并注册类名
  149. CString szClassName=AfxRegisterWndClass(CS_CLASSDC|CS_SAVEBITS|CS_HREDRAW|CS_VREDRAW,
  150. 0,(HBRUSH)GetStockObject(LTGRAY_BRUSH),0);
  151. if(!CWnd::CreateEx(0,szClassName,_T(""),WS_VISIBLE|WS_POPUP,p.x,p.y,100,100,
  152. pParentWnd->GetSafeHwnd(),0,NULL))
  153. return FALSE;
  154. if(szCustomText!=NULL)
  155. m_strCustomText=szCustomText;
  156. //设定窗体的尺寸
  157. SetWindowSize();
  158. //创建ToolTips显示的文字
  159. CreateToolTips();
  160. FindCellFromColour(crColour);
  161. SetCapture();
  162. return TRUE;
  163. }
  164. void CColourPopup::SetWindowSize()
  165. {
  166. CSize TextSize;
  167. //若显示用户文本区,则定义字体和文本尺寸
  168. if(m_bShowCustom)
  169. {
  170. //得到用户文本尺寸
  171. CClientDC dc(this);
  172. CFont* pOldFont=(CFont*)dc.SelectObject(&m_Font);
  173. TextSize=dc.GetTextExtent(m_strCustomText)+CSize(2*m_nMargin,2*m_nMargin);
  174. dc.SelectObject(pOldFont);
  175. //添加足够的空间来绘制水平线
  176. TextSize.cy+=2*m_nMargin+2;
  177. }
  178. m_nNumColumns=8;
  179. m_nNumRows=m_nNumColours/m_nNumColumns;
  180. if(m_nNumColours%m_nNumColumns) m_nNumRows++;
  181. //得到当前窗体位置,并设定新的尺寸
  182. CRect rect;
  183. GetWindowRect(rect);
  184. m_WindowRect.SetRect(rect.left,rect.top,rect.left+m_nNumColumns*m_nBoxSize+2*m_nMargin,
  185. rect.top+m_nNumRows*m_nBoxSize+2*m_nMargin);
  186. if(m_bShowCustom)
  187. {
  188. m_WindowRect.bottom+=(m_nMargin+TextSize.cy);
  189. if(TextSize.cx>m_WindowRect.Width())
  190. m_WindowRect.right=m_WindowRect.left+TextSize.cx;
  191. TextSize.cx=m_WindowRect.Width()-2*m_nMargin;
  192. m_TextRect.SetRect(m_nMargin,m_nMargin,
  193. m_nMargin+TextSize.cx,m_nMargin+TextSize.cy);
  194. }
  195. //检验是否超出了屏幕的显示范围
  196. CSize ScreenSize(::GetSystemMetrics(SM_CXSCREEN),::GetSystemMetrics(SM_CYSCREEN));
  197. //太靠右
  198. if(m_WindowRect.right>ScreenSize.cx)
  199. m_WindowRect.OffsetRect(-(m_WindowRect.right-ScreenSize.cx),0);
  200. //太靠左
  201. if(m_WindowRect.left<0)
  202. m_WindowRect.OffsetRect(-m_WindowRect.left,0);
  203. //底超出了屏幕
  204. if(m_WindowRect.bottom>ScreenSize.cy)
  205. {
  206. CRect ParentRect;
  207. m_pParent->GetWindowRect(ParentRect);
  208. m_WindowRect.OffsetRect(0,-(ParentRect.Height()+m_WindowRect.Height()));
  209. }
  210. MoveWindow(m_WindowRect,TRUE);
  211. }
  212. void CColourPopup::FindCellFromColour(COLORREF crColour)
  213. {
  214. for(int row=0;row<m_nNumRows;row++)
  215. for(int col=0;col<m_nNumColumns;col++)
  216. {
  217. if(GetColour(row,col)==crColour)
  218. {
  219. m_nChosenColourRow=row;
  220. m_nChosenColourCol=col;
  221. return;
  222. }
  223. }
  224. m_nChosenColourRow=TEXT_BOX_VALUE;
  225. m_nChosenColourCol=TEXT_BOX_VALUE;
  226. }
  227. void CColourPopup::CreateToolTips()
  228. {
  229. if(!m_ToolTip.Create(this)) return;
  230. for(int row=0;row<m_nNumRows;row++)
  231. for(int col=0;col<m_nNumColumns;col++)
  232. {
  233. CRect rect;
  234. if(!GetCellRect(row,col,rect)) continue;
  235. m_ToolTip.AddTool(this,GetColourName(row,col),rect,1);
  236. }
  237. }
  238. BOOL CColourPopup::GetCellRect(int row, int col, const LPRECT &rect)
  239. {
  240. if(row<0||row>=m_nNumRows||col<0||col>=m_nNumColumns)
  241. return FALSE;
  242. rect->left=col*m_nBoxSize+m_nMargin;
  243. rect->top=row*m_nBoxSize+m_nMargin;
  244. //当显示用户的文本时,将颜色板按钮部分下移
  245. if(m_bShowCustom)
  246. rect->top+=(m_nMargin+m_TextRect.Height());
  247. rect->right=rect->left+m_nBoxSize;
  248. rect->bottom=rect->top+m_nBoxSize;
  249. return TRUE;
  250. }
  251. void CColourPopup::OnPaint() 
  252. {
  253. //创建绘制的CDC派生类
  254. CPaintDC dc(this); // device context for painting
  255. //绘制颜色单元
  256. // TODO: Add your message handler code here
  257. for(int row=0;row<m_nNumRows;row++)
  258. for(int col=0;col<m_nNumColumns;col++)
  259. DrawCell(&dc,row,col);
  260. //写用户文本
  261. if(m_bShowCustom)
  262. DrawCell(&dc,TEXT_BOX_VALUE,TEXT_BOX_VALUE);
  263. //显示出凸出的按钮效果
  264. CRect rect;
  265. GetClientRect(rect);
  266. dc.DrawEdge(rect,EDGE_RAISED,BF_RECT);
  267. // Do not call CWnd::OnPaint() for painting messages
  268. }
  269. void CColourPopup::DrawCell(CDC *pDC,int row,int col)
  270. {
  271. if(m_bShowCustom&&row==TEXT_BOX_VALUE)
  272. {
  273. CRect TextButtonRect=m_TextRect;
  274. TextButtonRect.bottom-=(2*m_nMargin+2);
  275. //背景
  276. pDC->FillSolidRect(m_TextRect,::GetSysColor(COLOR_3DFACE));
  277. //按钮
  278. if(m_nCurrentRow==row&&m_nCurrentCol==col)
  279. pDC->DrawEdge(TextButtonRect,EDGE_RAISED,BF_RECT);
  280. //文本
  281. CFont *pOldFont=(CFont*)pDC->SelectObject(&m_Font);
  282. pDC->DrawText(m_strCustomText,TextButtonRect,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
  283. pDC->SelectObject(pOldFont);
  284. //文本下的水平线
  285. pDC->FillSolidRect(m_TextRect.left+2*m_nMargin,m_TextRect.bottom-m_nMargin-2,
  286. m_TextRect.Width()+4*m_nMargin,1,::GetSysColor(COLOR_3DSHADOW));
  287. pDC->FillSolidRect(m_TextRect.left+2*m_nMargin,m_TextRect.bottom-m_nMargin-1,
  288. m_TextRect.Width()+4*m_nMargin,1,::GetSysColor(COLOR_3DHILIGHT));
  289. return;
  290. }
  291. ASSERT (row>=0&&row<m_nNumRows);
  292. ASSERT (col>=0&&col<m_nNumColumns);
  293. //颜色板
  294. CPalette *pOldPalette;
  295. if(pDC->GetDeviceCaps(RASTERCAPS)&&RC_PALETTE)
  296. {
  297. pOldPalette=pDC->SelectPalette(&m_Palette,FALSE);
  298. pDC->RealizePalette();
  299. }
  300. CRect rect;
  301. if(!GetCellRect(row,col,rect)) return;
  302. //填充背景颜色
  303. if((m_nChosenColourRow==row&&m_nChosenColourCol==col)&&
  304. !(m_nCurrentRow==row&&m_nCurrentCol==col))
  305. pDC->FillSolidRect(rect,::GetSysColor(COLOR_3DHILIGHT));
  306. else
  307. pDC->FillSolidRect(rect,::GetSysColor(COLOR_3DFACE));
  308. //各个按钮
  309. if(m_nChosenColourRow==row&&m_nChosenColourCol==col)
  310. pDC->DrawEdge(rect,EDGE_SUNKEN,BF_RECT);
  311. else if(m_nCurrentRow==row&&m_nCurrentCol==col)
  312. pDC->DrawEdge(rect,EDGE_RAISED,BF_RECT);
  313. CBrush brush(PALETTERGB(GetRValue(GetColour(row,col)),
  314. GetGValue(GetColour(row,col)),
  315. GetBValue(GetColour(row,col))));
  316. CPen pen;
  317. pen.CreatePen(PS_SOLID,1,::GetSysColor(COLOR_3DSHADOW));
  318. CBrush* pOldBrush=(CBrush*)pDC->SelectObject(&brush);
  319. CPen* pOldPen= (CPen*)pDC->SelectObject(&pen);
  320. //绘各板单元的颜色
  321. rect.DeflateRect(m_nMargin+1,m_nMargin+1);
  322. pDC->Rectangle(rect);
  323. pDC->SelectObject(pOldBrush);
  324. pDC->SelectObject(pOldPen);
  325. brush.DeleteObject();
  326. pen.DeleteObject();
  327. if(pDC->GetDeviceCaps(RASTERCAPS)&RC_PALETTE)
  328. pDC->SelectPalette(pOldPalette,FALSE);
  329. }
  330. void CColourPopup::EndSelection(int nMessage)
  331. {
  332. ReleaseCapture();
  333. //如果用户文本被选中,拾色器
  334. if(nMessage!=CPN_SELENDCANCEL&&m_nCurrentCol==TEXT_BOX_VALUE&&m_nCurrentRow==TEXT_BOX_VALUE)
  335. {
  336. CColorDialog dlg(m_crInitialColour,CC_FULLOPEN|CC_ANYCOLOR,this);
  337. if(dlg.DoModal()==IDOK)
  338. m_crColour=dlg.GetColor();
  339. else
  340. m_crColour=m_crInitialColour;
  341. }
  342. if(nMessage==CPN_SELENDCANCEL)
  343. m_crColour=m_crInitialColour;
  344. m_pParent->SendMessage(nMessage,(WPARAM)m_crColour,0);
  345. DestroyWindow();
  346. }
  347. void CColourPopup::OnLButtonUp(UINT nFlags, CPoint point) 
  348. {
  349. // TODO: Add your message handler code here and/or call default
  350. CWnd::OnLButtonUp(nFlags, point);
  351. DWORD pos=GetMessagePos();
  352. point=CPoint(LOWORD(pos),HIWORD(pos));
  353. if(m_WindowRect.PtInRect(point))
  354. EndSelection(CPN_SELENDOK);
  355. else
  356. EndSelection(CPN_SELENDCANCEL);
  357. }
  358. void CColourPopup::OnMouseMove(UINT nFlags, CPoint point) 
  359. {
  360. // TODO: Add your message handler code here and/or call default
  361. int row,col;
  362. point.x-=m_nMargin;
  363. point.y-=m_nMargin;
  364. //检验鼠标是否在相应的区域
  365. if(m_bShowCustom&&m_TextRect.PtInRect(point))
  366. row=col=TEXT_BOX_VALUE;
  367. else
  368. {
  369. if(m_bShowCustom)
  370. point.y-=m_TextRect.Height();
  371. row=point.y/m_nBoxSize,
  372. col=point.x/m_nBoxSize;
  373. if(row<0||row>=m_nNumRows||col<0||col>=m_nNumColumns)
  374. {
  375. CWnd::OnMouseMove(nFlags,point);
  376. return;
  377. }
  378. }
  379. //得到相应行列,调用ChangeSelection
  380. if(row!=m_nCurrentRow||col!=m_nCurrentCol)
  381. ChangeSelection(row,col);
  382. CWnd::OnMouseMove(nFlags, point);
  383. }
  384. void CColourPopup::ChangeSelection(int row, int col)
  385. {
  386. CClientDC dc(this);
  387. if((m_nCurrentRow>=0&&m_nCurrentRow<m_nNumRows&&
  388. m_nCurrentCol>=0&&m_nCurrentCol<m_nNumColumns)||
  389. (m_nCurrentCol==TEXT_BOX_VALUE)) //TEXT_BOX_VALUE=-2
  390. {
  391. int OldRow=m_nCurrentRow;
  392. int Oldcol=m_nCurrentCol;
  393. m_nCurrentRow=m_nCurrentCol=-1;
  394. DrawCell(&dc,OldRow,Oldcol);
  395. }
  396. //选中的单元
  397. m_nCurrentRow=row;m_nCurrentCol=col;
  398. DrawCell(&dc,m_nCurrentRow,m_nCurrentCol);
  399. //选 中的单元颜色保存
  400. if(m_nCurrentRow==TEXT_BOX_VALUE&&m_nCurrentCol==TEXT_BOX_VALUE)
  401. m_pParent->SendMessage(CPN_SELCHANGE,(WPARAM)m_crInitialColour,0);
  402. else
  403. {
  404. m_crColour=GetColour(m_nCurrentRow,m_nCurrentCol);
  405. m_pParent->SendMessage(CPN_SELCHANGE,(WPARAM)m_crColour,0);
  406. }
  407. }
  408. void CColourPopup::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  409. {
  410. // TODO: Add your message handler code here and/or call default
  411. int row=m_nCurrentRow;
  412. int col=m_nCurrentCol;
  413. if(nChar==VK_DOWN)
  414. {
  415. if(row<0){row=0;col=0;}
  416. else if(row<m_nNumRows-1)row++;
  417. else {row=TEXT_BOX_VALUE;col=TEXT_BOX_VALUE;}
  418. ChangeSelection(row,col);
  419. }
  420. if(nChar==VK_UP)
  421. {
  422. if(row<0){row=m_nNumRows-1;col=0;}
  423. else if(row>0)row--;
  424. else {row=TEXT_BOX_VALUE;col=TEXT_BOX_VALUE;}
  425. ChangeSelection(row,col);
  426. }
  427. if(nChar==VK_RIGHT)
  428. {
  429. if(col<0){row=0;col=0;}
  430. else if(col<m_nNumColumns-1)col++;
  431. else col=0;
  432. ChangeSelection(row,col);
  433. }
  434. if(nChar==VK_LEFT)
  435. {
  436. if(col<0){row=m_nNumRows-1;col=m_nNumColumns-1;}
  437. else if(col>0)col--;
  438. else col=m_nNumRows;
  439. ChangeSelection(row,col);
  440. }
  441. if(nChar==VK_ESCAPE)
  442. {
  443. m_crColour=m_crInitialColour;
  444. EndSelection(CPN_SELENDCANCEL);
  445. return;
  446. }
  447. if(nChar==VK_RETURN)
  448. {
  449. EndSelection(CPN_SELENDOK);
  450. return;
  451. }
  452. CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  453. }
  454. BOOL CColourPopup::PreTranslateMessage(MSG* pMsg) 
  455. {
  456. // TODO: Add your specialized code here and/or call the base class
  457. m_ToolTip.RelayEvent(pMsg);
  458. return CWnd::PreTranslateMessage(pMsg);
  459. }
  460. void CColourPopup::OnPaletteChanged(CWnd* pFocusWnd) 
  461. {
  462. CWnd::OnPaletteChanged(pFocusWnd);
  463. // TODO: Add your message handler code here
  464. if(pFocusWnd->GetSafeHwnd()!=GetSafeHwnd())
  465. Invalidate();
  466. }
  467. BOOL CColourPopup::OnQueryNewPalette() 
  468. {
  469. // TODO: Add your message handler code here and/or call default
  470. Invalidate();
  471. return CWnd::OnQueryNewPalette();
  472. }
  473. void CColourPopup::OnNcDestroy() 
  474. {
  475. CWnd::OnNcDestroy();
  476. // TODO: Add your message handler code here
  477. delete this;
  478. }