对话框调用与背景小结

本文详细介绍了模态对话框与非模态对话框在Windows MFC中的调用方式,包括如何避免内存泄露。对于非模态对话框的大小调整和位置设置进行了说明,并讲解了如何获取用户输入数据。此外,还讨论了模态对话框的调用机制,涉及DoModal()函数的工作流程。文章进一步探讨了对话框颜色、控件颜色设置、文字颜色和位图插入的方法,提供了代码示例,展示了如何改变对话框背景、文字颜色以及实现透明效果。
摘要由CSDN通过智能技术生成

模态对话框的调用通常如下:
CDialog dia;
dia.DoModal();

而非模态对话框的调用如下:
CDialog *pDia;
pDia=new CDialog;
pDia.Create(IDD_DIALOG,this);
pDia.ShowWindow(SW_SHOW);
通常我们可以把pDia这个指针设为对话框所在类的成员变量,或者在类中重载PostNcDestroy(),在函数体中加delete this;来释放这个指针内存。这样就避免内存的泄露。在非模态对话框中可以在对话框显示前调用pDia->SetWindowPos(NULL,0,0,rect.Width(),rect.Height(),SWP_NOMOVE|SWP_NOZORDER);这里rect.Width(),rect.Height()分别是要显示后窗口的宽和高;如你要得到原窗口矩形,可以用pDia->GetWindowRect(&rect);

无论是模态还是非模态对话框要得到用户在上面编辑的数据,就要重载这个对话框的OnOk函数(如果是默认的OK Button,非默认的直接双击该Button就会生成响应函数),函数体中我们只要调用UpdateDate(TRUE);如果编辑控件没有关联变量,可以用GetDlgItemText(IDC_EDIT,str);把数据存在CString 对象str中。

对于非默认的Button要响应退出可以调用CDialog::OnCancle(); 建议是不要老是把对话框上的两个默认Button给删掉了。


下面讲下模态对话框的调用机制:

首先,DoModal()会使用对话框模板名来从应用程序的资源文件中查找、载入并锁定对话款模板。如果DoModal()不能定位资源,则返回错误代码-1

然后,这个函数会调用PreModal()PreModal会执行一些安全检查,然后为对话框查找父句柄(会通过CWnd::GetSafeOwner)。然后将结果保存在m_hWnd中。
之后,它会调用EnabledWindowFALSE)来冻结父窗口,强制式模态化~

接着他会准备将一个MFC对象粘贴到对话框中,通过AfxHookWindowCreate(注意MFC安装的CBT钩子)。然后调用CWnd::CreateDlgIndirect()。如果CreateDlgIndirect成功,DoModal就调用CWnd::RunModalLoop开启消息泵,这个消息泵一直等到用户按下OK或者CancelOnOKOnCancel都会自己调用EndDialog,然后EndDialog又调用CWnd::EndModalLoop
干掉RunModalLoop之后,DoModal会调用SetWindowPos隐藏已经被废掉的窗口,然后用EnabledWindow(TRUE)来激活父窗口,然后再调用SetActiveWidnow确保父窗口被激活;

最后,DoModal会调用DestroyWindow销毁窗体,然后调用PostModal,这个函数会通过Detach分离C++对象和Windows句柄(CWnd的知识),然后将m_hWndTop设置为NULL
然后在释放一些资源,清理一些东西,然后就返回RunModalLoop的返回值

//

对话框颜色设置:
如果想改变对话框的颜色可以为对话框添加一个WM_CTLCOLOR消息响应函数(专门为控件着色的消息响应函数),并在类中声名一个CBrush 的变量m_brush,在其构造函数中初始化:m_brush.CreateSolidBrush(RGB(255,0,0))//红色;下面返回画刷:
HBRUSH CSettingDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
   HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
   //return hbr;                    
   return m_brush;                      
}

如果我们要设置某一个对话框控件(如静态控件)的底色和文字颜色时只要将上面return m_brush;改为:
if (pWnd->GetDlgCtrlID()==IDC_STATIC)    
{
   pDC->SetTextColor(RGB(0,255,0));   
   pDC->SetBkColor(RGB(255,0,0));  
   return m_brush;               
}
return hbr;

利用上面的原理,在对话框控件响应OnPaint消息时,将一个静态文本显示所设置字体的文字。添加一个静态文本框,改名为IDC_TEXT。添加一个字体成员变量 private: CFont m_font;在对话框的构造

函数中对字体进行初始化:m_font.CreatePointFont(200,"华文行楷");2return hbr;之前加入如下代码:

if (pWnd->GetDlgCtrlID()==IDC_TEXT)  
{
   pDC->SelectObject(&m_font);   
}


对话框位图插入:
除了添加图像控件外,我们可以用代码来完成把对话框背景设为一幅位图。主对话框中有个OnPaint()函数,自己添加的对话框可以响应WM_PAINT消息;在OnPaint()函数中代码如下:

void 类名::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 CRect rect;
 GetClientRect(&rect);//得到客户区矩形
 CBitmap bip;bip.LoadBitmap(IDB_BITMAP1);//加载位图资源
 CDC comp;
 comp.CreateCompatibleDC(&dc);//创建兼容DC
 comp.SelectObject(&bip);//位图选入兼容DC
 dc.BitBlt(0,0,rect.Width(),rect.Height(),&comp,0,0,SRCCOPY);
 //从兼容DC中复制到目的DC中,其实我们还可以用>StretchBlt()这个函数(建议当窗口能变大小时用它),它多了两个关于位图宽度和高度的参数。
}

如果想在有位图的对话框上写些文字,可以在上面函数体尾部追加代码:
CString str="你要加的文字信息";
dc.SetBkMode(TRANSPARENT);//设置背景透明
dc.TextOut(x,y,str);//x,y为你开始输出的左上坐标

当然你可以创建你所需的字体,并设置颜色,也可以得到字体的信息和字符串的信息;
//创建字体
CFont font;
font.CreatePointFont(350,_T("华文行楷"),NULL);
CFont *oldfont=dc.SelectObject(&font);
……
dc.SelectObject(oldfont);
//设置字颜色
de.SetTextColor(GRB(a,b,c));
//得到字体信息
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
//得到字符串在屏幕上输出的宽度和高度存入CSize对象中
CSize c=dc.GetTextExtent(str);


在基于文档类插入位图时,就要响应WM_ERASEBKGND消息,如:
BOOL 类名::OnEraseBkgnd(CDC* pDC)
{
 
CBitmap bip;
bip.LoadBitmap(IDB_BITMAP1);
BITMAP map;//定义包含位图信息的对象
bip.GetBitmap(&map);
CDC dcom;dcom.CreateCompatibleDC(pDC);
dcom.SelectObject(&bip);
CRect rect;
GetClientRect(&rect);//得到客户区矩形
pDC->StretchBlt(0,0,rect.Width(),rect.Height(),&dcom,0,0,map.bmWidth,map.bmHeight,SRCCOPY);
return true;//原函数体中是返回的false,把它改为TRUE
}
这样窗口大小变化时位图也是整幅的显示在窗口上。
注:这个函数体内的内容可以写在OnDraw()函数体中,但是效果不很好;因为OnDraw()函数会调用OnPaint(),而OnPaint()调用前会发送刷新窗口的消息WM_ERASEBKGND并返回false;所以在这个消息的响

应函数中加载位图更快,要注意的是,我们要把返回值改为TRUE,否则加载的位图又被刷新得没有。


当然可以让字体在窗口上渐变输出,这样就要加一个定时器,并响应WM_TIMER消息
OnTimer()中添加代码,这时我们输出文字应该用DrawText()其中有个参数是输出文字的矩形的长度
我们可以让它从0,渐变到文字的总长度,这样就可以渐变输出了(提示:把这个int 型变量声名为static型);

 

 

TransparentBltStretchBltBitBlt

BOOL StretchBlt( int x, //指定目的矩形区域左上角的X坐标 int y, //指定目的矩形区域左上角的Y坐标 int nWidth, //指定目的矩形区域的宽度 int nHeight, //指定目的矩形区域的高度 CDC* pSrcDC, int xSrc, //指定源矩形区域左上角的X坐标 int ySrc, //指定源矩形区域左上角的Y坐标 int nSrcWidth, //指定源矩形区域的宽度 int nSrcHeight, //指定源矩形区域的高度 DWORD dwRop //此参数参考MSDNSRCCOPY类型为直接拷贝 ); //此函数将一个位图资源从一个矩形区域拷贝到另一个矩形区域,即缩放位图 

BOOL TransparentBlt( int xDest, int yDest, int nDestWidth, int nDestHeight, CDC*pSrcDC, intxSrc, intySrc, intnSrcWidth, intnSrcHeight, UINTclrTransparent ); //此函数同样具有缩放功能,但此函数最后一个参数用来指定作为透明色的RGB 

BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop ); //此函数同样用来拷贝位图资源,但不具备缩放功能 

用法举例: 

CPaintDC dc(this);
   CBitmap BackBMP;
   BackBMP.LoadBitmapW(IDB_BITMAP1);
   BITMAP bm;
   BackBMP.GetBitmap(&bm); 

   CDC ImageDC;
   ImageDC.CreateCompatibleDC(&dc);
   CBitmap* pOldImageBMP = ImageDC.SelectObject(&BackBMP);
   dc.StretchBlt(0, 0, bm.bmWidth+15, bm.bmHeight+15, &ImageDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
   ImageDC.SelectObject(pOldImageBMP);
  
   CBitmap ForeBMP;
   ForeBMP.LoadBitmapW(IDB_BITMAP2);
   ForeBMP.GetBitmap(&bm); 

   pOldImageBMP = ImageDC.SelectObject(&ForeBMP);
   dc.TransparentBlt(0, 0, bm.bmWidth+15, bm.bmHeight+15, &ImageDC, 0, 0, bm.bmWidth, bm.bmHeight, RGB(255, 255, 255));
   ImageDC.SelectObject(pOldImageBMP);

  

TransparentBlt用法


 
 

 TransparentBlt 函数在Windows98/Windows2000以上版本运行,系统中需要包含 Msimg32.dll,使用时可以链接 Msimg32.lib
 Windows98下的TransparentBlt会产生资源泄漏,所以不建议在WIN98下使用该函数。
 TransparentBlt函数原型如下:
 
 
 BOOL TransparentBlt(
 HDC hdcDest,      // 目标DC
 int nXOriginDest,   // 目标X偏移
 int nYOriginDest,   // 目标Y偏移
 int nWidthDest,     // 目标宽度
 int hHeightDest,    // 目标高度
 HDC hdcSrc,         // DC
 int nXOriginSrc,    // X起点
 int nYOriginSrc,    // Y起点
 int nWidthSrc,      // 源宽度
 int nHeightSrc,     // 源高度
 UINT crTransparent  // 透明色,COLORREF类型
 );
 
 
 使用例子:
 
 
  CBitmap DispBmp;
  CBitmap *OldBmp;
  CDC SourceDC;
  DispBmp.LoadBitmap("TEST_BITMAP");//如果是IDB_XXX则不需加引号!
  SourceDC.CreateCompatibleDC(PDC);
  OldBmp = SourceDC.SelectObject(&DispBmp);
  ::TransparentBlt(PDC->m_hDC,0, 0,128, 128, SourceDC.m_hDC,0,0,128,128,RGB(0,0,0));
  SourceDC.SelectObject(OldBmp);
 
 
 要注意的是TransparentBlt函数使用的位图是8位或者24位的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值