几个函数,告别MFC自带调色板
BOOL CWnd::SetWindowPos(const CWnd* pWndInsertAfter,int x,int y,int cx,int cy,UINT nFlags);
void CRect::SetRect(int x1,int y1,int x2,int y2) throw( );
void CDC::FillSolidRect(LPCRECT lpRect,COLORREF clr );
绘制每个色条都不是什么麻烦的事情,麻烦的是怎么让色彩过渡更平滑,美观。
这个调色板有很多人性化的设计,很直观。
上半部分,每个色带里面可选的颜色值都是256个值,而颜色的范围则是由另外2个原色当前选定值决定的。
下半部分,从上到下,是一个灰度阶梯,从左到右,则是三原色的真值变化(当然你把它看作是256进制的数),具体变化如下:
R:255 -》255 -》0 -》0 -》0 -》255 -》255
G:0 -》255 -》255 -》255 -》0 -》0 -》0
B:0 -》0 -》0 -》255 -》255 -》255 -》0
注意:这个真值表,每次只有一项真值发生了变化。
然后整体从左上角到右下角时,遵循的规律是:(J是从左到右发生变化的某个真值递增值)
255-》255 0-》0 255《-》0
前H/2: 255 255递减到0 255递减到J
后H/2 255递减到0 0 J递减到0
在OnInitDialog()重新设定元素的位置。
色条的边框是用静态文本的Client Edge效果出来的。
当然要归功于SetWindowPos的切割。
GetDlgItem(IDC_STATIC_RC)->GetWindowRect(&rcStaticR);
ScreenToClient(&rcStaticR);
GetDlgItem(IDC_STATIC_RC)->SetWindowPos(NULL,rcStaticR.left,rcStaticR.top,157,\
rcStaticR.bottom-rcStaticR.top-2,SWP_NOMOVE|SWP_NOZORDER);
设置CSliderCtrl的范围,我的颜色条是153个像素的。
m_cSliderR.SetRange(1,153,false);
颜色条的绘制区高度,是要去掉边框的,自绘的话,边框值好设定和得到。我这里没有重绘,6是我试出来的,左右边框。
m_uiStaticRHigh=rcStaticR.bottom-rcStaticR.top-6;
在OnPaint里绘制色条
得到拖拉条现在的位置:
int nRpos=m_cSliderR.GetPos();
获得DialogItem的DC,一定要用子元素自己的DC绘制;
CDC *pDcR=GetDlgItem(IDC_STATIC_RC)->GetDC();
禁止DialogItem自绘,一个小技巧。
GetDlgItem(IDC_STATIC_RC)->Invalidate(false);
GetDlgItem(IDC_STATIC_RC)->UpdateWindow();
绘制:
for(;i <153;i++ ){
rectangle.SetRect(i,0,i+1, m_uiStaticRHigh);
pDcR->FillSolidRect(&rectangle, RGB(i/3*5,nGpos/3*5,nBpos/3*5));
}
绘制下面的条子,灰度我从上到下共绘制26个像素,这是6段里面的第一段,其他的如法炮制:
i=0;
CRect rc;
for(int j=0;j<=36;j++){
for(int k=0;k<=25;k++){
rc.SetRect(i,k,i+1,k+1);
if(k<=12)
pDcAll->FillSolidRect(&rc,RGB(255,255-(255-j*7)*k/13,255-255*k/13));
else
pDcAll->FillSolidRect(&rc,RGB(255-255*(k-12)/13,j*7-j*7*(k-12)/13,0));
}
i++;
}
接下来就是处理消息循环,处理CEdit的ON_EN_CHANGE,CSliderCtrl的NM_RELEASEDCAPTURE和 ON_WM_HSCROLL,处理下面条子的ON_WM_LBUTTONDOWN,ON_WM_MOUSEMOVE,ON_WM_LBUTTONUP。
来源:考试大 为什么不在HSCROLL中处理鼠标的拖拽和方向键拖拉呢,这样导致的结果是频繁的重绘。另外,每次要重新绘制的时候并不是调用Invalidate,而是另外添加个函数,只会上面的部分,下部分没必要重绘。
另外要处理方向键拖动拖拉条。
BOOL CPalletteDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if(pMsg->message==WM_KEYUP){
if(pMsg->wParam==37||pMsg->wParam==38||pMsg->wParam==39||pMsg->wParam==40){
OnPaintEX();//只绘上半部分
}
}
return CDialog::PreTranslateMessage(pMsg);
}
责任编辑:cyth