MFC绘制CListCtrl单元格颜色+重绘窗体背景+电脑桌面绘制图片等

来源:互联网 发布:火箭军 知乎 编辑:程序博客网 时间:2024/04/29 14:51

提示://假设你现在有一个窗体类 CPosition

先给童鞋补一个重写窗体函数的小技巧,以防产生无谓的疑惑:

·打开你的ClassView

·Add Windows Message Handler

·根据你的需要添加tiemrpaintsizeclose ……

·有的童鞋可能删除了某些编译器给你自动生成的配置文件导致以上行为无法实现,不用担心,

那就打开你的ResourceView,打开你的对话框,右键添加类向导,选择添加全部即可恢复。

 

一、设置CListCtrl单元格的颜色

MFCCListCtrl默认的颜色是屎灰色,有时候我们需要表格有不同的颜色表示不同的数据,

让数据有不同的状态或者有其他不同的特性。为了达到这个目的,我们只需要重写函数OnCustomdrawMyList

废话不多说,直接看代码,废话都在代码中的注释里面。

//表格颜色的重绘是按照一次只重绘每一行的每一列来进行的

void  CPosition::OnCustomdrawMyList ( NMHDR* pNMHDR, LRESULT* pResult )

{

    NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );

    *pResult = CDRF_DODEFAULT;

   //第一件事-检查画阶段。如果是控制阶段,返回,我们希望的是每一行列的消息。

    if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )

        {

        *pResult = CDRF_NOTIFYITEMDRAW;

        }

    else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )

        {

        

//这是一个行的通知消息

 

        *pResult = CDRF_NOTIFYSUBITEMDRAW;

        }

    else if ( (CDDS_ITEMPREPAINT | CDDS_SUBITEM) == pLVCD->nmcd.dwDrawStage )

        {

              //用例表示字体颜色和背景颜色

COLORREF crText, crBkgnd;

CString strTemp;

//判断买卖

        int nItem = static_cast<int>( pLVCD->nmcd.dwItemSpec);

CHeaderCtrl* pHeaderCtrl = m_tradelist.GetHeaderCtrl();

 

              //定义五个状态,分别用来判断五列是否存在

int dir =-1; //方向

int hold =-1; //状态1

int holdbyday =-1; //状态2

int holdbytick =-1; //状态3

              //!!!!!!!!!!!!!!!!!!!!!!重要!!!!!!!!!!!!!!!!!!!!!

//这个地方是你需要做的,你需要自己定义上面四个状态,即自己的四列值是否存在,

              //如果确定是存在的,就把这四个值设为对应的列数 1 2 3 4 

              //!!!!!!!!!!!!!!!!!!!!!!重要!!!!!!!!!!!!!!!!!!!!!

 

if(dir != -1&&pLVCD->iSubItem ==dir) //如果存在这一列并且正在绘制这一列

{

strTemp =m_tradelist.GetItemText(nItem,dir);

if(strcmp(strTemp,"") ==0)

{

crText = RGB(255,0,0);       //text 红色

crBkgnd = RGB(192,192,192);   //背景颜色  白色:255,255,255  银白色:192,192,192

}

else if(strcmp(strTemp,"") ==0)

{

crText = RGB(0,128,0 );//字体颜色  纯绿色

crBkgnd = RGB(192,192,192);//背景颜色  银白色

}

else

{

crText = RGB(0,0,0);       //text  字体黑色  

crBkgnd = RGB(255,235,255);     //淡粉色  

}

}

else if(hold != -1&&pLVCD->iSubItem ==hold) //如果存在这一列并且正在绘制这一列

{

strTemp =m_tradelist.GetItemText(nItem,hold);

Porl =atof(strTemp);

if(Porl >0)

{

crText = RGB(255,0,0);       //text 红色

crBkgnd = RGB(192,192,192);   //背景颜色  白色:255,255,255  银白色:192,192,192

}

else if(Porl <0)

{

crText = RGB(0,128,0 );//字体颜色  纯绿色

crBkgnd = RGB(192,192,192);//背景颜色  银白色

}

else

{

crText = RGB(0,0,0);       //text  字体黑色  

crBkgnd = RGB(255,235,255);     //淡粉色  

}

}

else if(holdbyday != -1&&pLVCD->iSubItem ==holdbyday) //如果存在这一列并且正在绘制这一列

{}

else if(holdbytick != -1&&pLVCD->iSubItem ==holdbytick) //如果存在这一列并且正在绘制这一列

{}

else

{

crText = RGB(0,0,0);       //text  字体黑色  

crBkgnd = RGB(255,235,255);     //淡粉色  

}

        // Store the colors back in the NMLVCUSTOMDRAW struct.

        pLVCD->clrText = crText;//将设置好的属性赋值 并去真正影响控件属性

        pLVCD->clrTextBk = crBkgnd;

         // Tell Windows to paint the control itself.

        *pResult = CDRF_DODEFAULT;

        }

}

当绘制每一个单元格的时候,先去判断这一列是否存在,如果存在,再根据这个单元格中的内容,

是为A还是为B,是大于0还是小于等于0来赋不同的值给颜色局部变量,最后再将局部变量赋值给

该单元格的颜色变量。就OK了。

 

二、重绘窗体背景

按照文章开头的方式,重定义一下你的窗口OnPaint函数就好了,当然你首先要做以下工作:

·增加图片资源,在FileView视图中添加资源,添加bmp(等),其ID默认就行啦。

当然VC6.0VS2000系列有些不同,所以还不如不细写,大家随便尝试一下就OK了。

void CPosition::OnPaint() 

{

  CPaintDC   dc(this);

  CRect      rect;

  GetClientRect(&rect);

  CDC        dcMem;

  dcMem.CreateCompatibleDC(&dc);

  CBitmap bmpBackground;

      bmpBackground.LoadBitmap(IDB_BITMAP1);

      BITMAP  bitmap;

      bmpBackground.GetBitmap(&bitmap);

      CBitmap  *pbmpOld=dcMem.SelectObject(&bmpBackground);

      dc.StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);

// device context for painting

// TODO: Add your message handler code here

// Do not call CDialog::OnPaint() for painting messages

}

 

三、电脑桌面绘制图片

 

熟悉CDC的童鞋应该会觉得以下总结会比较简单:

在桌面上绘制图片只需要两步:获取桌面CDC句柄,绘制

1.

加载图片资源的方法在上面 重绘窗体背景 中已经讨论了。之后我们需要获取桌面句柄:

大家可以尝试一个最简单的MFC基于对话框的工程,主窗体是CFreeMFCDlg,写一个按钮,

在按钮单击响应事件里面加入如下代码

CWnd* pwnd = GetDesktopWindow();

//获取当前桌面的设备上下文

CDC* pdc = pwnd->GetWindowDC();

CString str;

str = "老婆我爱你!";

pdc->TextOut(100, 130, str);

COLORREF color = RGB(0, 255, 0);

CBitmap *bmp =new CBitmap;

bmp->LoadBitmap(IDB_BITMAP3);

DrawBitmap(pdc, bmp,40,40,color);

 

pdc->TextOut(100, 130, str);这一句对大家来说是太简单了吧

之后是设置一个颜色,加载图片资源,然后调用DrawBitmap()绘图,代码奉上:

void CFreeMFCDlg::DrawBitmap(CDC* pDC, CBitmap* pBitmap,

short xStart, short yStart, COLORREF cColor)

{

BITMAP     bm;

COLORREF   cColor;

CBitmap    bmAndBack, bmAndObject, bmAndMem, bmSave;

CBitmap    *pbmBackOld, *pbmObjectOld, *pbmMemOld, *pbmSaveOld;

CDC        dcMem, dcBack, dcObject, dcTemp, dcSave;

CPoint     ptSize;

dcTemp.CreateCompatibleDC(pDC);

dcTemp.SelectObject(pBitmap);  

pBitmap->GetObject(sizeof(BITMAP), (LPSTR)&bm);

ptSize.x = bm.bmWidth;

ptSize.y = bm.bmHeight;

dcTemp.DPtoLP(&ptSize, 1);  

dcBack.CreateCompatibleDC(pDC);

dcObject.CreateCompatibleDC(pDC);

dcMem.CreateCompatibleDC(pDC);

dcSave.CreateCompatibleDC(pDC);

bmAndBack.CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);

bmAndObject.CreateBitmap(ptSize.x, ptSize.y, 1, 1, NULL);

bmAndMem.CreateCompatibleBitmap(pDC, ptSize.x, ptSize.y);

bmSave.CreateCompatibleBitmap(pDC, ptSize.x, ptSize.y);

pbmBackOld = dcBack.SelectObject(&bmAndBack);

pbmObjectOld = dcObject.SelectObject(&bmAndObject);

pbmMemOld = dcMem.SelectObject(&bmAndMem);

pbmSaveOld = dcSave.SelectObject(&bmSave);

dcTemp.SetMapMode(pDC->GetMapMode());

dcSave.BitBlt(0, 0, ptSize.x, ptSize.y, &dcTemp, 0, 0, SRCCOPY);

cColor = dcTemp.SetBkColor(cColor);

dcObject.BitBlt(0, 0, ptSize.x, ptSize.y, &dcTemp, 0, 0, SRCCOPY);

dcTemp.SetBkColor(cColor);

dcBack.BitBlt(0, 0, ptSize.x, ptSize.y, &dcObject, 0, 0, NOTSRCCOPY);

dcMem.BitBlt(0, 0, ptSize.x, ptSize.y, pDC, xStart, yStart, SRCCOPY);

dcMem.BitBlt(0, 0, ptSize.x, ptSize.y, &dcObject, 0, 0, SRCAND);

dcTemp.BitBlt(0, 0, ptSize.x, ptSize.y, &dcBack, 0, 0, SRCAND);

dcMem.BitBlt(0, 0, ptSize.x, ptSize.y, &dcTemp, 0, 0, SRCPAINT);

pDC->BitBlt(xStart, yStart, ptSize.x, ptSize.y, &dcMem, 0, 0, SRCCOPY);

dcTemp.BitBlt(0, 0, ptSize.x, ptSize.y, &dcSave, 0, 0, SRCCOPY);

(dcBack.SelectObject(pbmBackOld))->DeleteObject();

(dcObject.SelectObject(pbmObjectOld))->DeleteObject();

(dcMem.SelectObject(pbmMemOld))->DeleteObject();

(dcSave.SelectObject(pbmSaveOld))->DeleteObject();

dcMem.DeleteDC();

dcBack.DeleteDC();

dcObject.DeleteDC();

dcSave.DeleteDC();

dcTemp.DeleteDC();

}

运行之后就OK!

这只是个接口,至于怎么用,请发挥想象力。

2.

直接调用桌面CDC绘制,如果刷新频率等处理不好,会出现闪屏花屏的现象,

现在比较流行的方法是建一个透明的全屏的窗体,让这个窗体透明,然后在窗体上进行绘制。

 

在初始化窗体的时候

//将窗口动态设置成分层窗口

LONG t = GetWindowLong(m_hWnd, GWL_EXSTYLE); //GWL_EXSTYLE=-20

t |= WS_EX_LAYERED;  //WS_EX_LAYERED=80000h=524288d

SetWindowLong(m_hWnd, GWL_EXSTYLE, t);

SetLayeredWindowAttributes(0, 50, LWA_ALPHA |  LWA_COLORKEY);

//设置窗口的大小,最大化窗口

ShowWindow(SW_SHOWMAXIMIZED);

帮大家百科了一下SetLayeredWindowAttributes的函数:

BOOL SetLayeredWindowAttributes(

HWND hwnd, // 指定分层窗口句柄

COLORREF crKey, // 指定需要透明的背景颜色值,可用RGB()

BYTE bAlpha, // 设置透明度,0表示完全透明,255表示不透明

DWORD dwFlags // 透明方式

);

LWA_ALPHA:crKey参数无效,bAlpha参数有效;

LWA_COLORKEY:窗体中的所有颜色为crKey的地方将变为透明,bAlpha参数无效。

LWA_ALPHA | LWA_COLORKEY : crKey的地方将变为全透明,而其它地方根据bAlpha参数确定透明度。

上述代码中的透明度是50,运行后屏幕是不是像贴了层膜?透明度设置为零的时候就看不到你的窗口了,

然后,尤其是对CDC很熟悉的童鞋do something you want.

 

只是简单介绍一下,可以加Q 1466231850讨论。

0 0
原创粉丝点击