孙鑫: 第十讲 绘图

 

第十讲  绘图
对话框中的OKBUtton对应的是OnOk函数,这个函数可以认为默认的会调用UpDateData使变量更新。
 If the dialog box includes automatic data validation and exchange, the default implementation of this member function validates the dialog-box data and updates the appropriate variables in your application.
 
 颜色对话框的创建
   用类CColorDialog。
  
   如果想要设置颜色对话框的初始颜色没,应该设置CHOOSECOLOR结构体成员变量m_cc的flag设为CC_RGBINIT,然后将想要初始化的颜色赋给rgbResult。
   见MSDN
    If the CC_RGBINIT flag is set, rgbResult specifies the color initially selected when the dialog box is created.
   可以在对话框构造函数中设置,也可以创建后在成员变量m_cc中设置。
   typedef struct {   // cc
    DWORD        lStructSize;
    HWND         hwndOwner;
    HWND         hInstance;
    COLORREF     rgbResult;
    COLORREF*    lpCustColors;
    DWORD        Flags;    //要初始化颜色必须设置这个
    LPARAM       lCustData;
    LPCCHOOKPROC lpfnHook;
    LPCTSTR      lpTemplateName;
} CHOOSECOLOR;

注意:
 dlg.m_cc.Flags = CC_RGBINIT;  这样赋值是错误的,因为m_cc已经有了一个标记???
 应该是
  dlg.m_cc.Flags |= CC_RGBINIT;
 
  初始化颜色的两种方法:
  1. CColorDialog color;
      color.m_cc.Flags |= CC_RGBINIT;
      color.m_cc.rgbResult = initcol;
  2.  CColorDialog color(initcol);
  标记CC_FULLOPEN的意思是让颜色设置窗口完全展开。
  获取用户选择的颜色可以用m_cc结构体中的rgbResult,也可以用GetColor().
 
字体对话框的创建
  用类CFontDialog
 
  通过对话框返回的m_cc中的LPLOGFONT    lpLogFont;创建一个字体用以下方法
  CFont::CreateFontIndirect (lpLogFont);
 
  一个奇怪的问题
  CFont font;
  CFont *p = (CFont *)pDC->SelectObject(font);
  这样居然没有错,而且能运行一次.
  正确的应该是
   CFont font;
   CFont *p = pDC->SelectObject(&font);
  
   当font已经创建好了,即已经和一种字体资源关联起了,再次调用font.CreateFontIndirect()就会出错,应该先释放这个资源,
 用基类的函数CGdiObject::DeleteObject ()
 
    Deletes the attached Windows GDI object from memory by freeing all system storage associated with the Windows GDI object. The storage associated with the CGdiObject object is not affected by this call. An application should not call DeleteObject on a CGdiObject object that is currently selected into a device context.
   
    判断一个字体时候已经和一种资源关联,和以前的一样,用句柄来判断,CGdiObject::m_hObject ,从CGdiObject派生的都可以这样。
    当编辑框上输入改变的时候发送的是EN_CHANGE消息。
   
  怎样改变对话框或者控件的背景颜色和文字颜色
 
  一个消息响应函数 绘制控件背景色。
  当要绘制控件时候发送WM_CTRLCOLOR消息
  所有控件绘制时候都会调用,想改变控件就需要在这个函数中进行区分,例如通过ID.
  if(pWnd->GetDlgCtrlID == ID_****)
  {
     CBrush brush;
     brush.CreateSolidBrush(RGB(255,0,0)); //改变背景色的画刷
     pDC->SetTextColor(RGB(255,0,0)); //将控件文本颜色设置为红色
     pDC->SetBkMode(TRANSPARENT);     //文本背景设为透明
     return brush;
  }
   CWnd::OnCtlColor 
  afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor );
  
  Return Value
  
  OnCtlColor must return a handle to the brush that is to be used for painting the control background.
  
  CWnd::GetDlgCtrlID 
  int GetDlgCtrlID( ) const;
  
  Return Value
  
  The numeric identifier of the CWnd child window if the function is successful; otherwise 0.
  
  Remarks
  
  Returns the window or control ID value for any child window, not only that of a control in a dialog box. Since top-level windows do not have an ID value, the return value of this function is invalid if the CWnd is a top-level window.
  GetDlgCtrlID 返回一个子控件ID也可以返回其他子窗口。
  设置文字颜色
   pDC->SetTextColor()'
  设置文字背景
    CDC::SetBkMode 
    int SetBkMode( int nBkMode );
    
    Return Value
    
    The previous background mode.
    
    Parameters
    
    nBkMode
    
    Specifies the mode to be set. This parameter can be either of the following values:
    
    OPAQUE   Background is filled with the current background color before the text, hatched brush, or pen is drawn. This is the default background mode.
    
    
    TRANSPARENT   Background is not changed before drawing.
    
    将文字背景设置为透明:
     pDC->SetBkMode(TRANSPARENT);
    
  
  如果要改变一个单行编辑框的背景颜色,除了要返回一个颜色画刷以外,还要调用CDC::SetBkColor函数。
  To change the background color of a single-line edit control, set the brush handle in both the CTLCOLOR_EDIT and CTLCOLOR_MSGBOX message codes, and call the CDC::SetBkColor function in response to the CTLCOLOR_EDIT code.
  
  对于一个单行编辑框来说,应该如下来改变背景颜色和文字颜色:
  
 if(pWnd->GetDlgCtrlID == ID_EDIT1)
  {
     CBrush brush;
     brush.CreateSolidBrush(RGB(255,0,0)); //改变背景色的画刷
     pDC->SetTextColor(RGB(255,0,0)); //将控件文本颜色设置为红色
     pDC->SetBkColor(RGB(0,0,255));
     return brush;
  }
 
   绘制一个静态字体的时候设置字体
  
   if(pWnd->GetDlgCtrlID == IDC_TEXT)
   {
       pDC->SelectObject(&font);
   }
  
  绘制Button的时候设置它的背景色和文字颜色
  
   if(pWnd->GetDlgCtrlID == IDC_BUTTON1)
   {
      在此这些都不能改变BUtton的背景和文字颜色
   }
   原因:
    这是因为在自绘制Button的时候会调用CButton::DrawItem 函数,通过CButton::DrawItem 函数的参数LPDRAWITEMSTRUCT lpDrawItemStruct 中保存的DC来绘制。
    Called by the framework when a visual aspect of an owner-drawn button has changed. An owner-drawn button has the BS_OWNERDRAW style set. Override this member function to implement drawing for an owner-drawn CButton object. The application should restore all graphics device interface (GDI) objects selected for the display context supplied in lpDrawItemStruct before the member function terminates.
   
    所以要改变一个Button的颜色比较麻烦,需要创建自定义的Button类继承与CButton,然后覆盖这个函数CButton::DrawItem,在这个函数中修改lpDrawItemStruct中DC的画刷和设置文本颜色。例如我们自定义了类MyButton。
    接着在需要改变的Button上关联一个MyButton 控件变量 ,然后在资源管理器中将这个 Button的OWNER_DRAW属性勾选上。
   
  
   如何在一个窗口上显示一个位图
  
     1.创建位图。
      CBitmap bitmap;
      bitmap.LoadBitmap(IDC_MAP1);
     2.创建一个兼容DC
      CDC dc;
      dc.CreateCompatibleDC(pDC);
     
      说明:
      CDC::CreateCompatibleDC 
      virtual BOOL CreateCompatibleDC( CDC* pDC );

      Creates a memory-device context that is compatible with another device context. You can use it to prepare images in memory. 
      刚创建的时候兼容DC的大小为1*1个像素。
     
    3.将位图选送到兼容DC中。
    
      dc.SelectObject(&bitmap);
      //这时候兼容DC的大小和bitmap大小一样。
     
    4.将兼容DC的位图贴到当前DC中
   
    pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(),&dc,0,0,SRCCOPY);
   
    说明:
    Bitblt()//按1:1比例拷贝
    Copies a bitmap from the source device context to this current device context.
    拷贝一个位图从源DC到当前DC
   
    WM_ERASEBKGND
An application sends the WM_ERASEBKGND message when the window background must be erased (for example, when a window is resized). The message is sent to prepare an invalidated portion of a window for painting.

当一个窗口背景需要被檫除的时候发送消息WM_ERASEBKGND

  CWnd::GetClientRect  得到客户区大小
  Copies the client coordinates of the CWnd client area into the structure pointed to by lpRect. The client coordinates specify the upper-left and lower-right corners of the client area. Since client coordinates are relative to the upper-left corners of the CWnd client area, the coordinates of the upper-left corner are (0,0).
 
  如果想要让源位图拷贝到新DC中能自动调整大小适应新的DC,要改用:
  CDC::StretchBlt
  通过Bitmap::GetBitmap()可以得到位图大小
 
  窗口重绘的两个过程
   1.发送WM_ERASEBKGND消息,檫除背景。
   2.发送WM_PAINT消息,从新绘制背景。
  
   把绘制代码放到OnDraw里它会先檫除在绘制,所以闪烁大些,而在响应WM_ERASEBKGND消息的函数里则是直接绘制,所以闪烁小些。
  
 
  目前不知道怎么从一个工程里边去处一个类,不过我是直接在目录下删除,然后删除.dsp文件中的相关信息。
 
  孙老师最后说的那个问题我的解决方法是
    建立一个类派生于CDialogBar,需要注意的是用向导不能直接生成(起码我这是),所以先生成继承于CDialog的,然后手动修改,
 添加响应消息WM_CTRLCOLOR函数,然后在此函数中和视频中讲的一样的操作。这样对话框颜色和编辑框颜色可以修改。
    不过我在这个函数里边进行贴图操作没有成功,还不知道怎么回事,而且在OnPaint函数也不行。
   
    切记,自定义消息的映射宏是ON_MESSAGE.
    刚才自定义了一个消息,然后再OnCreate函数里发送,在消息处理函数里边进行贴图操作,结果是初始化没有图,但当点击DialogBar上的任何一个控件的时候这个图就出来了。
    靠,刚经过别人帮我检查发现我的自定义消息的,在映射中没有使用消息名而用的是别的如下。
   #define UM_PIC WM_USER+20
 ON_MESSAGE(WM_USER,OnPic) ;//这样显然是错的

ON_MESSAGE(UM_PIC,OnPic) ;//准确的

    经过修改可以了,不过要记得PostMessage()要在OnPaint中调用,否则只是刚开始出现一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值