OnCtlColor
每个控件在绘制时,都会向父窗口(通常都是dialog)发送一个WM_CTLCOLOR消息,用来返回一个Cbrush
句柄,用来绘制自己.
HBRUSH CDlgDialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (nCtlColor == CTLCOLOR_DLG)
{
return m_brush;
}
return hbr;
}
pDC是为绘制自己而准备的,pWnd是发送消息的控件窗体的对象指针,nCtlColor代表发送消息的控件的类型,如:
CTLCOLOR_BTN Button control
CTLCOLOR_DLG Dialog box
CTLCOLOR_EDIT Edit control
CTLCOLOR_LISTBOX List-box control
CTLCOLOR_MSGBOX Message box
CTLCOLOR_SCROLLBAR Scroll-bar control
CTLCOLOR_STATIC Static control
如果用来判断是哪一类控件可以用这个值,如何用来精确控件哪一个控件,可以用
pWnd->GetDlgCtrlID() 返回控件的ID
if (nCtlColor == CTLCOLOR_DLG)
{
return m_brush;
}
if (pWnd->GetDlgCtrlID() == IDC_EDIT1)
{
m_brush.DeleteObject();
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);
m_brush.CreatePatternBrush(&bmp);
return m_brush;
}
如果改变字体的颜色可以为pDC选择相应的设备对象
DrawItem
在OnCtlColor, CButton是不被控件的。要改变CButton的绘制,要重载CButton类的DrawItem方法,具体可以查看MSDN
OnEraseBkgnd
以上对bitmap的操作,都是作为brush进行刷背景,现在介绍一下如何显示出一副位图
OnEraseBkgnd对应的事件发生在背景重绘时,这是从CWnd继承下来的一个方法。可以在这个事件中将
一幅图显示在CView, CDialog等类的背景上。
OnEraseBkgnd事件可以在Cview的子类上用类向导添加,但vc6中,CDialog中是不能用类向导添加的。可以直接手工添加消息响应函数
BOOL CDlg_DCTest1::OnEraseBkgnd(CDC* pDC)
{
CDC dc;
dc.CreateCompatibleDC(pDC);
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1);
dc.SelectObject(&bmp);
CRect rect;
GetClientRect(&rect);
//显示全图
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &dc, 0, 0, SRCCOPY);
BITMAP bitmap;
bmp.GetBitmap(&bitmap);
return true;
}
BitBlt函数说明:参数1,2是目的DC开始粘贴的起始点, 参数6,7是源DC开始拷贝的起始点。参数3,4是拷贝和粘贴的大小
icon绘制
CClientDC dc(this);
HICON hIcon = ::LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDI_ICON1));
//HICON hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
dc.DrawIcon(8, 8, hIcon);
icon可以通过两种方式加载,然后用dc进行绘制.
sdk中的loadicon第一个参数是指icon所在程序的应用程序实例句柄
绘制不规则窗体
OnInitDialog中实现即可
//改变窗体形状
CRect rect;
GetClientRect(&rect);
m_rgn.CreateEllipticRgn(0, 0, rect.Width(), rect.Height());
SetWindowRgn(m_rgn, true);
SetWindowRgn会将CRgn m_rgn;描述的形状显示成窗体形状
绘制随意形状的窗体
下面是一个按钮事件中的方法
CClientDC dc(this);
//创建字体
CFont mFont;
VERIFY(mFont.CreateFont(
200, 50, 0, 0, FW_HEAVY, TRUE, FALSE,
0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_SWISS, "宋体"));
dc.BeginPath();
//必须
dc.SetBkMode(TRANSPARENT);
CFont *pOldFont = (CFont *)dc.SelectObject(&mFont);
dc.SelectObject(&mFont);
dc.TextOut(0, 0, "中华民族");
mFont.DeleteObject();
dc.SelectObject(pOldFont);
dc.EndPath();
HRGN hrgn;
hrgn=PathToRegion(dc);
SetWindowRgn(hrgn, true);
根据dc的beginpath endpath之前,dc画出的路径,可以转化为hrgn,然后设置窗体。
移动没有title bar的窗体(CDialog窗体)
通过响应WM_NCHITTEST来实现
头文件中对消息的声明:
afx_msg UINT OnNcHitTest(CPoint point);
源文件中的定义:
ON_WM_NCHITTEST()
UINT CDlgDlg::OnNcHitTest(CPoint point)
{
//Let user move window by clickign anywhere on the window .
UINT nHitTest = CDialog :: OnNcHitTest (point) ;
return (nHitTest == HTCLIENT)? HTCAPTION: nHitTest ;
}
响应函数是指当鼠标落在窗体上时,变为拖拽模式模式。
对CView这种有控件覆盖在主窗体上的程序,可以在网上查一下具体做法:
http://www.vckbase.com/document/viewdoc/?id=464
设置没有title bar 窗体在状态栏上的文字
OnInitDialog中实现就可以
//此处可以设置没有title bar的窗体在任务栏上的显示标题
char *str = "abc";
SendMessage(WM_SETTEXT, 0, (LPARAM)str);