孙鑫VC++深入详解(9):绘图控制

1、CColorDialog为MFC的颜色选择对话框。

2、CFontDialog为MFC的字体选择对话框。

3、CBrush、CPen、CFont、CBitmap等GDI对象都派生于CGdiObject类,要释放GDI对象先前关联的资源可以调用CGdiObject::DeleteObject()函数;要判断GDI对象是否已经于某个资源相关联了,可以通过判断CGdiObject的数据成员m_hObject来实现。

4、当CEdit控件上的文本发生改变时,它会向其父窗口发送EN_CHANGE通知消息(它自己则会收到=EN_CHANGE反射消息)。在对话框资源上右击CEdit控件,选择“添加事件处理程序”,消息类型选择EN_CHANGE,类列表选择对话框类,可以为对话框添加EN_CHANGE消息事件处理程序。

    类似的,当CButton控件被点击时,它会向其父窗口发送BN_CLICKED消息(它自己则会收到=BN_CLICKED反射消息),故为按钮添加“单击”事件处理程序应选择BN_CLICKED消息类型。

5、WM_CTLCOLOR消息对应响应函数原型:

afx_msg HBRUSH OnCtlColor(
   CDC* pDC,
   CWnd* pWnd,
   UINT nCtlColor 
);
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(静态文本控件)

  该函数返回将被用来绘制控件或父窗口(通常是对话框)的画刷句柄,故可以通过改变其返回值来改变控件或对话框的背景颜色(对话框背景的绘制也会调用 OnCtlColor这个函数)。如:改变对话框及其子控件的背景颜色:

HBRUSH CDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  在此更改 DC 的任何属性

	// TODO:  如果默认的不是所需画笔,则返回另一个画笔	
	<strong>//return hbr;
	static CBrush brush(RGB(0,0,255));
        return brush;//CBrush重载了HBRUSH操作符,故可以返回CBrush类型</strong>
}
 如果想要改变指定控件的背景颜色,可以通过第二个参数pWnd调用GetDlgCtrlID()获得当前控件的ID;如果要改变控件的字体颜色则可以使用第一个参数控件的上下文调用SetTextColor()设置控件的字体颜色;需要注意的是如果要改变单行编辑框控件的背景颜色,除了返回设置的画刷外,还应调用SetBkColor()设置编辑控件的背景颜色。eg:
HBRUSH CDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  在此更改 DC 的任何属性

	// TODO:  如果默认的不是所需画笔,则返回另一个画笔	
	if(pWnd->GetDlgCtrlID() == IDC_EDIT1)
	{
            pDC->SetTextColor(RGB(255,0,0));    
            pDC->SetBkColor(RGB(0,0,255));
            static CBrush brush(RGB(0,0,255));
            return brush;
 	}

	return hbr;
}

  如果是按钮控件的话,则改变其背景颜色和文本颜色应该重载按钮类的DrawItem()函数,并设置自绘属性,需要注意的是在DrawItem返回前,一定要恢复lpDrawItemStruct->pDC中原有对象,如果改变了的话。 函数原型:

virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
参数 lpDrawItemStruct 指向的结构体包含将要绘制的信息和要绘制的类型

typedef struct tagDRAWITEMSTRUCT {
   UINT CtlType;
   UINT CtlID;
   UINT itemID;
   UINT itemAction;
   UINT itemState;
   HWND hwndItem;
   HDC hDC;
   RECT rcItem;
   DWORD itemData;
} DRAWITEMSTRUCT;
  CtlType:控件类型,为以下值之一:ODT_BUTTON 自绘制按钮
                                                                     ODT_COMBOBOX 自绘制组合框
                                                                     ODT_LISTBOX 自绘制列表框
                                                                     ODT_MENU 自绘制菜单项
                                                                     ODT_LISTVIEW 自绘制列表视
                                                                     ODT_STATIC 自绘制静态控件
                                                                     ODT_TAB Tab控件

  CtlID控件ID,对于菜单项无需使用

  itemID菜单项ID或列表框、组合框中某项的索引值,对于一个空的列表框或组合框,该成员的值为-1。

  itemAction绘制动作,可以为以下值之一或组合:ODA_DRAWENTIRE 整个控件都需被绘制
                                                                                              ODA_FOCUS 控件需要获得或失去焦点时被绘制
                                                                                              ODA_SELECT 控件需要在被选中时绘制

  itemState当前绘制完成后的,所绘项的可见状态,有以下几种取值:

                                                                                              ODS_CHECKED 如果菜单项将被选中,该值被设置(只对菜单项有效)

                                                                                              ODS_DISABLED 如果绘制项将被禁止,该值被设置
                                                                                              ODS_FOCUS 如果绘制项需要输入焦点,该值被设置
                                                                                              ODS_GRAYED 如果绘制项需要被灰色显示,则该值被设置
                                                                                              ODS_SELECTED 如果绘制项需要被设置为选中状态,则该值被设置
                                                                                              ODS_COMBOBOXEDIT 在自绘制组合框中只绘制选择区域

                                                                                              ODS_DEFAULT 自绘制项为默认项,表示当前控件处于默认状态;

  hwndItem指定了组合框、列表框和按钮等自绘制控件的窗口句柄如果为菜单项,则为示包含该菜单项的菜单句柄。

  hDC绘制操作所使用的设备环境。

  rcItem将被绘制的矩形区域,这个矩形区域就是上面hDC的作用范围。系统会自动裁剪组合框、列表框或按钮等控件的自绘制区域以外的部分。也就是说rcItem中的坐标点(0,0)指的就是控件的左上角。但是系统不裁剪菜单项,所以在绘制菜单项的时候,必须先通过一定的换算得到该菜单项的位置,以保证绘制操作在我们希望的区域中进行。

  itemData对于菜单项,该成员的取值可以是由CMenu::AppendMenu、CMenu::InsertMenu或者CMenu::ModifyMenu等函数传递给菜单的值;对于列表框或组合框,该成员的值可以为由ComboBox::AddString、CComboBox::InsertString、CListBox::AddString或者CListBox::InsertString等传递给控件的值;如果ctlType是ODT_BUTTON或ODT_STATIC,itemData则为0。

eg:改变按钮的背景颜色和文本颜色:

void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	// TODO:  添加您的代码以绘制指定项

	//绘制按钮框架
	UINT uStyle = DFCS_BUTTONPUSH;

   // This code only works with buttons.
   ASSERT(lpDrawItemStruct->CtlType == ODT_BUTTON);

   // If drawing selected, add the pushed style to DrawFrameControl.
   if (lpDrawItemStruct->itemState & ODS_SELECTED)
      uStyle |= DFCS_PUSHED;

   // Draw the button frame.
   ::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, DFC_BUTTON, uStyle);


	CDC dc;
	dc.Attach(lpDrawItemStruct->hDC);

	//设置按钮背景颜色
	CBrush brush(RGB(0,255,0));
	dc.FillRect(&lpDrawItemStruct->rcItem,&brush);

	//设置按钮文本颜色
	CString strText;
	GetWindowText(strText);
	COLORREF clr_tx = dc.SetTextColor(RGB(255,0,0));
	int bkMode_old = dc.SetBkMode(TRANSPARENT);
	dc.DrawText(strText, strText.GetLength(), &lpDrawItemStruct->rcItem, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
	
	//恢复hDC中原有对象
	dc.SetBkMode(bkMode_old);
	dc.SetTextColor(clr_tx);
	dc.Detach();
}
6、为对话框资源视图上的按钮关联自定义类型的成员变量:例如CMyButton类是从CButton继承而来的类,现在为按钮关联一个CMyButton类型的成员变量:右击按钮—>添加变量—>变量类型选择CMyButton—>勾选控件变量。

7、显示位图

 

                     pSrcDC指向源设备上下文对象。

                      xSrc和ySrc指定源矩形区域左上角的x坐标和y坐标。

要在窗口中显示一张位图,首先向工程资源中插入一张位图,ID设为IDB_BITMAP1。

窗口的绘制包含两个过程:先擦除背景,然后再对窗口重新进行绘制。当擦除窗口背景时,会发送WM_ERASEBKGND消息,故可以在视类窗口的WM_ERASEBKGND消息响应函数中实现位图的显示,同时应屏蔽掉擦除窗口背景的操作:

BOOL CtestView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	
	//创建位图对象
	CBitmap bitmap;
	bitmap.LoadBitmap(IDB_BITMAP1);

	//创建与当前DC兼容的DC
	CDC dcCompatible;
	dcCompatible.CreateCompatibleDC(pDC);

	//将位图对象选入到兼容DC中
	dcCompatible.SelectObject(&bitmap);

	//将兼容DC中位图画到当前DC中
	CRect rect;
	GetClientRect(&rect);
	pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &dcCompatible, 0, 0, SRCCOPY);
	
	return TRUE;
	//return CView::OnEraseBkgnd(pDC);//屏蔽擦除窗口背景
}

CDC::StretchBlt()函数与BitBlt()功能相似,不同的是如果目标矩形区域比源矩形区域大或小,则BitBlt()不会对源矩形区域进行拉伸或压缩, StretchBlt()则多了两个参数来指示源矩形区域大小,在复制时可以自动拉伸和压缩源像素区域,以适合目的矩形区域的尺寸。在当前程序中,源矩形区域的大小即为选入的位图对象的宽度和高度,位图对象的宽度和高度可以通过调用CBitmap::GetBitmap(BITMAP* pBitMap)获得,该函数返回位图对象的相关信息到一个BITMAP结构中,其中包括位图的宽度和高度:

typedef struct  tagBITMAP
  {
      LONG        bmType;
      LONG        bmWidth; //位图宽度
      LONG        bmHeight;//位图高度
      LONG        bmWidthBytes;
      WORD        bmPlanes;
      WORD        bmBitsPixel;
      LPVOID      bmBits;
  } BITMAP, *PBITMAP, NEAR *NPBITMAP, FAR *LPBITMAP;

BOOL CtestView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	
	//创建位图对象
	CBitmap bitmap;
	bitmap.LoadBitmap(IDB_BITMAP1);
	BITMAP bmp;
	bitmap.GetBitmap(&bmp);

	//创建兼容DC
	CDC dcCompatible;
	dcCompatible.CreateCompatibleDC(pDC);

	//将位图对象选入到兼容DC中
	dcCompatible.SelectObject(&bitmap);

	//将兼容DC中位图画到当前DC中
	CRect rect;
	GetClientRect(&rect);
	pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &dcCompatible, 0, 0, 
					bmp.bmWidth, bmp.bmHeight, SRCCOPY);

	return TRUE;
	//return CView::OnEraseBkgnd(pDC);
}
其它需要注意的地方:




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以作为课程设计的程序,实现简单的绘图,移动图形的功能。 使用vc框架实现。 GHpaint程序的几个重点 程序的基本功能: 程序提供绘图、删除已绘图形、移动已绘图形。 可以选择绘图颜色、形状、线粗。 重点问题: 1、 程序设计基于面向对象。 程序中所有图形都从基类CShapebase派生,大部分工作(例如:删除、移动等)都在这个基类中完成。此类中的两个纯需函数: //纯需函数DrawShape,每个基类都必须实现的函数。 //指定不同图形的绘制方法。 virtual void DrawShape(CDC* pdc) = 0; //橡皮筋效果的算法函数 virtual void ZoomShape(CDC *pdc) = 0; 这两个函数需要在派生类中重载。这两个函数中主要实现不同图形的绘制方法。 也就是说,不同图形的不同点只有绘制方法不同,其他所有属性和行为都可以统一处理。 这里的继承体现了面向对象的设计,论文中可以体现这一点。 2、 动态模板库对象CPtList的使用,动态模板库基础知识。 CPtList是动态模板库的一个实例化类。功能是以链表形式保存指针,至于指针类型不做要求,需要程序员自己设计。 本程序CPtList对象中保存所有图形对象指针,由于所有图形都从CShapebase派生,所以所有图形指针都可以转化为基类CShapebase指针后保存在CPtList中。以后再遍历列表,调用图形对象函数时出现了多态调用。这里体现面向对象程序的多态,论文中可以说明。 至于CPtList的使用,可以在网上查查,可以看看程序代码,比较简单。 多态:是一种函数调用形式。出现在类继承情况下。详细的多态定义到网上查查。 程序中的多态体现在CShapebase类的虚函数,在使用CShapebase指针调用这两个虚函数,实际调用的使子类的重载函数体。这里实际上是不知道函数怎样工作,但是知道函数功能。 例如:使用CShapebase指针调用DrawShape函数,因为不知道子类是什么图形,所以不知道DrawShape怎样画这个图,但是直到DrawShape函数会把这个图画好,这就达到了要求。 3、 Windows窗口绘图基本知识。 3.1 Windows GUI绘图基本知识。使用MFC类库之后,每个窗口都有一个CDC指针量。这个变量提供图形绘制。CDC类说明查查网络,内容比较多。CDC及提供图形绘制算法,也提供各种绘制模式(单色、异或色等),提供画笔和画刷的功能。 3.2 窗口绘图基本思想: 图形绘制在窗口中,windows不会帮助程序员让图形“长在”窗口上,当窗口被遮挡,最小化后,图形绘消失。程序需要在合适的时机把图形重新画在窗口上。所以窗口上画的内容需要程序员自己思考怎样保存。在本程序中所有图形保存在CPtList对象中。 3.2 Windows为窗口提供了一个重绘消息:OnPaint,在winxp系统中,这个消息会在窗口被遮挡部分从新出现、窗口从最小化恢复时调用。在win7种只有窗口从屏幕外移动进屏幕时调用。具体情况可以查查网络,这里是我的发现,并不是主要内容。 在OnPaint消息中重新绘制所有图形是一个保证图形不消失的好办法。 4、 Windows颜色控制基本知识。 4.1 windows使用RGB三原色(红绿蓝)提供颜色控制,本程序使用24位颜色,在内存中占用4字节,所以用int型表示,但是int型的最高位字节不使用,这样每一种颜色就有一个字节表示,每种颜色级别从0-255。系统提供RGB宏帮助定义颜色,例如:RGB(255,0,0)是红色,RGB(0,0,0)黑色,RGB(255,255,255)白色。 4.2 windows绘图提供多种颜色混合模式,本程序中使用异或模式实现图形的“橡皮筋”效果和移动效果,使用纯色模式定位图形。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值