学习心得之八------实现从磁盘读入图片文
之前写《学习心得之七---程序启动画面的设计》时心思来潮想写个像word那样类似的启动画面,后来发现,有点难,最起码从电脑磁盘读取图片文件就实现不了,捣鼓了一晚上,终于有眉目了,写篇心得咯。
首先,我们创建一个基于对话框的工程LoadBmp,然后我们在ID号为IDD_LOADBMP_DIALOG的对话框中删除原有控件,加三个控件----静态控件,编辑框控件,按钮控件:
我们将静态控件的Caption改为“请从磁盘加载位图资源文件”,修改编辑框,按钮控件的ID号:
IDC_FILENAME;
IDC_BROWSE;
并为按钮控件关联一个成员变量m_filename,如图:
我们在编辑框控件上右击鼠标,选择classwizard,按照如图步骤添加成员变量,我们在第四步时,不选择value,而是control。完成后,我们在CLoadBmpDlg的头文件中,添加一个成员变量:
class CLoadBmpDlg : public CDialog
{
// Construction
public:
CLoadBmpDlg(CWnd* pParent = NULL); // standard constructor
HBITMAP m_hBmp;
//省略代码
}
并在构造函数中将其设为NULL;
CLoadBmpDlg::CLoadBmpDlg(CWnd* pParent /*=NULL*/)
: CDialog(CLoadBmpDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CLoadBmpDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_hBmp=NULL;
}
接下来,我们处理"..."按钮单击消息。首先创建类向导,生成消息函数:
void CLoadBmpDlg::OnBrowse()
{
// TODO: Add your control notification handler code here
CFileDialog filedlg(TRUE);
if(filedlg.DoModal()==IDOK)
{
CString szfile=filedlg.GetPathName();
m_FileName.SetWindowText(szfile);
if (m_hBmp != NULL)
{
DeleteObject(m_hBmp);
m_hBmp = NULL;
}
m_hBmp = (HBITMAP)LoadImage(NULL, szfile,IMAGE_BITMAP,
0, 0, LR_LOADFROMFILE);
OnPaint();
}
}
我们要从磁盘读取文件,当然少不了CFileDialog类了,它与《学习心得之五,MFC编程中两种文件对话框的创建》里的创建步骤一样,我们就不细分过滤文件了,接下来我们得到文件的路径使用函数Getpathname(),并将选择的磁盘文件的路径写到编辑框中,调用函数setwindowtext();我们判断下是否已经选择了图片文件,因此加个if语句,这是个好习惯哦!接着我们使用函数LoadImage()加载图片:
HANDLE LoadImage(
HINSTANCE hinst,
LPCTSTR lpszName,
UINT uType,
int cxDesired,
int cyDesired,
UINT fuLoad
);
第一个参数,可以为NULL,就是图像的实例句柄;
第二个参数,如果从磁盘加载的,就是文件路径咯,否则就是图像的资源名称
第三个参数,加载的类型,IMAGE_BITMAP:装载位图;IMAGE_CURSOR:装载光标;IMAGE_ICON:装载图标。
第四个参数,表示图表或鼠标的宽度,如果是位图那就是0;
第五个参数,同上,只不过表示的是高度,
最后表示加载类型,如果是LR_LOADFROMFILE,表示从磁盘加载文件。
返回值是加载的图像句柄,但我们需要的是位图句柄,因此强制类型转化咯。
最后我们调用OnPaint(),使用WM_PAINT消息绘图。
void CLoadBmpDlg::OnPaint()
{
if (IsIconic())
{
//省略代码 }
else
{
///加上的代码:
if(m_hBmp!=NULL)
{
CDC *pDC=GetDC();
CBitmap bmp;
bmp.Attach(m_hBmp);
CDC memDC;
memDC.CreateCompatibleDC(pDC);
memDC.SelectObject(&bmp);
BITMAP BitInfo;
bmp.GetBitmap(&BitInfo);
int x=BitInfo.bmweight;
int y=BitInfo.bmHeight;
pDC->BitBlt(10,50,x,y,&memDC,0,0,SRCCOPY);
bmp.Detach();
memDC.DeleteDC();
}
}
}
我们创建设备描述表对象,并返回一个DC指针,然后创建一个位图类,并将我们之前LoadImage返回的位图句柄附属到我们的CBitmap上,我们定义一个设备描述表对象,并用它创建一个兼容DC,我们看看函数CreateCompatibleDC:
HDC CreateCompatibleDC(HDC hdc);
接下来我们选入我们的位图对象bmp,我们定义一个BITMAP的对象,接受位图bmp的信息,并用变量x,y接受位图的高,宽,最后就是函数BitBlt();该函数用于从原设备中复制位图到目标设备。具体参数我们可以查MSDN;点击《VS2015离线MSDN安装包下载地址和各版本在线MSDN入口地址》,我们就能查到了。我这就不详述了。看看是想实现结果吧
如果我们觉得图片太小了(原谅我是个鸟橱,个人兴趣),将函数BitBlt的调用改为函数StrechBlt的调用就行了,这个函数实现延伸图片,铺满客户区,只不过图片分辨率就会降低。