概述

本程序软件的主要实现垃圾文件清理的功能,即对指定的文件格式的临时文件或垃圾文件进行遍历、扫描、显示、删除清理等功能。在程序界面设计方面,对默认对话框重新自定义绘制,主要包括标题栏的重绘、对话框边框的重绘、对话框背景重绘、以及最小化按钮、最大化按钮和关闭按钮等的重绘实现。经过界面的设计和功能的实现开发,从而开发出一款具有实用意义的垃圾清理工具。

详细

代码下载:http://www.demodashi.com/demo/13430.html

一、简要概述

先来上个图吧:

下面就是详细介绍开发这个小程序的大体方法和步骤吧。程序是基于VC++程序设计与开发为背景,着重分析了垃圾文件清理原理和对话框程序界面的设计与开发原理,首先简要介绍VC++程序设计开发的基本方法;然后说明垃圾文件清理的原理和以绘制位图技术为背景的对话框绘制界面技术,最后重点介绍了垃圾清理程序的设计与实现。

1:概述:

本程序的主要实现垃圾文件清理的功能,即对指定的文件格式的临时文件或垃圾文件进行遍历、扫描、显示、删除清理等功能。在程序界面设计方面,对默认对话框重新自定义绘制,主要包括标题栏的重绘、对话框边框的重绘、对话框背景重绘、以及最小化按钮、最大化按钮和关闭按钮等的重绘实现。经过界面的设计和功能的实现开发,从而开发出一款具有实用意义的垃圾清理工具。

2:开发环境:

程序开发平台是基于Microsoft Visual Studio 2008 集成开发环境,编程技术采用Visual C++(MFC) 编程技术,以及相关的开发软件如Photoshop CS5等。

3:需求分析:

本程序的设计与开发主要分为两大模块,功能的设计开发和应用程序界面的设计开发。

功能的分析与设计:垃圾清理功能主要包括文件遍历扫描、显示已扫描到的文件以及垃圾文件的删除清理等。用户需要一边进行文件扫描,另一边可以对已经扫描到的垃圾文件进行清理操作。文件扫描通常会占用大量的时间,为了提高垃圾清理的可靠性和效率,应该使用多线程开发技术,即将文件扫描的任务放置在一个单独的线程中即可。

应用程序界面设计:在对话框重绘中,使用的主要技术有两个,一个是绘制对话框的背景位图,在对话框大小改变时能够输出位图,使位图能够适应对话框的大小。另一个是在对话框的指定区域输出位图。

二、核心功能设计、开发和实现

下面我们就是开始代码实现了,下面先开始实现功能部分,即垃圾文件的扫描、显示和清理。

功能的分析与设计:垃圾清理功能主要包括文件遍历扫描、显示已扫描到的文件以及垃圾文件的删除清理等。用户需要一边进行文件扫描,另一边可以对已经扫描到的垃圾文件进行清理操作。文件扫描通常会占用大量的时间,为了提高垃圾清理的可靠性和效率,应该使用多线程开发技术,即将文件扫描的任务放置在一个单独的线程中即可

(1)创建一个基于对话框的工程,工程名称为“ClearTmpFile”。

(2)向对话框中添加静态文本框、按钮、组合框、列表框、进度条等控件,效果如下:

控件布局图

(3)在对话框类CClearTmpFileDlg中添加共有的主要数据成员,各成员功能见注释部分:

CList<CString, CString> m_fileExtList;//记录需要查找临时文件扩展名bool m_bThreadExit;//线程是否退出bool m_bFinding;//是否查找进行中HANDLE m_hThread;//查找文件的线程句柄HANDLE m_hThread2;//bmp旋转线程句柄CString m_szCurDisk;//查找的磁盘HANDLE m_hEvent;//事件对象,在对话框关闭时将提前结束查找bool m_bContinue;//判断暂停或继续按钮操作DWORD GetDiskSize(char* strPath);//获取磁盘容量(已使用的)DWORD m_dwDiskVol;//磁盘总容量大小,单位为KBDWORD m_dwScanedVol;//已扫描的文件的容量DWORD m_dwScanedTmpFileVol;//扫描到的临时文件的容量大小DWORD m_dwScanedTmpFileNum;//扫描到的临时文件的容量大小

(4)向对话框类中添加ResearchFile方法,判读指定的目录,将指定的垃圾文件类型显示在扫描结果列表中。

void CClearTmpFileDlg::ResearchFile(char * pszPath)
{    char szTmp[MAX_PATH]={0};//定义一个临时字符数组    strcpy(szTmp,pszPath);    if(szTmp[strlen(szTmp)-1]!='\\')//将目录以“\\*.*”形式结尾    {strcat(szTmp,"\\*.*");//连接字符串    }    else{strcat(szTmp,"*.*");//连接字符串    }WIN32_FIND_DATA findData;//定义一个文件查找数据结构memset(&findData,0,sizeof(WIN32_FIND_DATA));    HANDLE hFind = FindFirstFile(szTmp,&findData);//开始查找文件    //由于查找是在线程中进行的,这里判读用户是否退出线程,如果是则提前结束线程函数    if(m_bThreadExit)    {FindClose(hFind);//关闭查找句柄SetEvent(m_hEvent);//设置事件为有信号return;}    if(hFind != INVALID_HANDLE_VALUE)//文件查找成功    {        while(FindNextFile(hFind,&findData)==TRUE)//查找下一个文件{//由于查找是在线程中进行的,这里判读用户是否退出线程,如果是则提前结束线程函数if (m_bThreadExit){FindClose(hFind);//关闭查找句柄SetEvent(m_hEvent);//设置事件为有信号return;}            //如果文件不是一个目录if(!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){DWORD dwFileSize = (findData.nFileSizeHigh* (MAXDWORD+1) + findData.nFileSizeLow)/(1024);//获取文件大小,单位为KBm_dwScanedVol += dwFileSize;//累计已扫描文件的容量大小,单位为KB                //m_dwScanedVol = m_dwScanedVol/1024;//单位转换为:MB                //设置进度条进度m_progressCtl.SetPos((m_dwScanedVol/1024));                char szFileName[MAX_PATH] = {0};//定义字符数组,存储完整的文件名strcpy(szFileName,pszPath);//获取完整文件名if(szFileName[strlen(szFileName)-1] != '\\'){strcat(szFileName,"\\");}strcat(szFileName,(char *)findData.cFileName);                if(IsTmpFile(szFileName))//判断szFileName是否是临时文件                {m_dwScanedTmpFileVol += dwFileSize;//累计扫描到的临时文件容量大小,单位为KBm_dwScanedTmpFileNum ++;//累计扫描到的临时文件的数目                    m_listBoxResults.AddString((LPCTSTR)szFileName);}}            else//如果文件是一个目录,则递归遍历该目录            {                if((strcmp((const char *)&findData.cFileName,"...")!=0) &&(strcmp((const char *)&findData.cFileName,"..")!=0)&&(strcmp((const char *)&findData.cFileName,".")!=0)){                    char szFileName[MAX_PATH]={0};strcpy(szFileName,pszPath);//获取完整文件名if(szFileName[strlen(szFileName)-1]!='\\'){strcat(szFileName,"\\");}strcat(szFileName,(char *)findData.cFileName);                    //由于查找是在线程中进行的,这里判读用户是否退出线程,如果是则提前结束线程函数if(m_bThreadExit){FindClose(hFind);//关闭查找句柄SetEvent(m_hEvent);//设置事件为有信号return;}ResearchFile(szFileName);//递归调用                }}}}FindClose(hFind);//关闭文件查找句柄}

(5)定义线程函数,用来单独执行扫描查找垃圾文件任务:

DWORD _stdcall FindTmpFile(LPVOID lpParameter)
{CClearTmpFileDlg* pDlg = (CClearTmpFileDlg*) lpParameter;//获取线程参数WaitForSingleObject(pDlg->m_hEvent,INFINITE);//等待事件有信号CString dir = pDlg->m_szCurDisk.GetBuffer();//根据当前盘符目录磁盘目录char *s = (LPSTR)(LPCTSTR)dir;        pDlg->ResearchFile(s);    pDlg->Restore();pDlg->ShowResultText();//显示扫描临时文件的数目和大小    //恢复数据为初始状态pDlg->m_dwScanedTmpFileVol = 0;pDlg->m_dwScanedTmpFileNum = 0;pDlg->m_fileExtList.RemoveAll();    return 0;
}

(6)处理“立即扫描”或“开始”按钮的单击事件,创建一个新的线程执行扫描文件的任务:

//如果查找没有结束,则不允许开始新的文件查找GetDlgItem(IDC_BEGIN)->ShowWindow(SW_HIDE);    if(!m_bFinding && GetTmpExtName())//获取文件扩展名    {GetDlgItem(IDC_PROGRESS1)->ShowWindow(TRUE);//显示进度条        GetDlgItem(IDC_LIST1)->ShowWindow(SW_SHOW);        m_bThreadExit  = FALSE;m_bFinding = TRUE;m_combox.GetWindowText(m_szCurDisk);//获取当前盘符        // 初始化进度条相关数据m_dwDiskVol =GetDiskSize((LPSTR)(LPCTSTR)m_szCurDisk);//获取当前磁盘的容量大小(已使用的)        CString str;str.Format(_T("%d"),m_dwDiskVol/(1024));        double iSize = atoi(str);m_progressCtl.SetRange32(0,m_dwDiskVol/1024);//初始化进度条,设置进度条的范围,范围为MB的数量if(m_hEvent!=NULL){CloseHandle(m_hEvent);//关闭事件对象m_hEvent = NULL;}m_listBoxResults.ResetContent();//清空查找结果列表m_hEvent = CreateEvent(NULL,FALSE,TRUE,_T("Event"));//创建事件对象        //创建一个线程,开始执行线程函数m_hThread = CreateThread(NULL,0,FindTmpFile,this,0,NULL);    m_hThread2 = CreateThread(NULL,0,RotatingImg,this,0,NULL);            UpdateData(FALSE);

(7)清理已扫描到的垃圾文件,即采用删除文件策略,使用DeleteFile()方法:

void CClearTmpFileDlg::OnBnClickedDelall()
{//删除已扫描到的垃圾文件    CString strDel;CFile file;    for(int i=0;i<m_listBoxResults.GetCount();i ++){m_listBoxResults.GetText(i,strDel);GetDlgItem(IDC_TEST)->SetWindowText(strDel);DeleteFile(strDel);//删除指定路径的文件        }m_listBoxResults.ResetContent();GetDlgItem(IDC_TEST)->SetWindowText(_T("清理完毕!"));GetDlgItem(IDC_LIST1)->ShowWindow(SW_HIDE);GetDlgItem(IDC_BEGIN)->ShowWindow(SW_SHOW);GetDlgItem(IDC_BEGIN)->SetWindowText(_T("重新扫描"));
}

好了,到此差不多软件的主要功能部分都已经开发完毕,大家已经看出来了,功能部分很简单,就是对指定的文件格式进行扫描、显示和清理。下面将进行对软件界面的设计与开发。

三、程序软件的UI界面设计与实现

对应用程序界面的设计包括两部分,一部分是对话框自身的重设计,二是对话框控件的重绘,本程序主要对按钮控件进行重绘设计。

1. 绘制对话框的背景位图

绘制对话框背景位图本文采用的是处理对话框的WM_PAINT消息,该消息初始化时候对对话框进行绘制,从而绘制背景位图。绘制背景位图的主要代码如下:

CRect   rect;CPaintDC   dc(this);GetClientRect(&rect); //获取客户区
//设置对话框背景颜色        dc.FillSolidRect(rect,RGB(14,94,157));   //设置为窗口背景

2. 在指定的区域中输出位图

为了能够在指定的区域中输出位图,需要使用设备上下文CDC类的StretchBlt方法。由于我们需要在窗口的非客户区域绘制位图,因此需要使用CWindowDC类的StretchBlt方法, CWindowDC类派生与CDC类,它提供了在窗口非客户区域绘制位图的功能。该方法数从源矩形中复制一个位图到目标矩形,必要时按目前目标设备设置的模式进行图像的拉伸或压缩。输出位图的主要实现代码如下:

CRect winRC;CDC* pDC=GetWindowDC();//获取窗口设备上下文    CDC memDC;memDC.CreateCompatibleDC(pDC);//创建兼容内存位图    BITMAPINFO bmpInfo;CBitmap bmp;    //定义位图对象GetWindowRect(&winRC);bmp.LoadBitmap(nID);//加载位图bmp.GetObject(sizeof(BITMAPINFO),&bmpInfo);//获取位图信息int nBmpCX = bmpInfo.bmiHeader.biWidth;//获取位图宽度int nBmpCY = bmpInfo.bmiHeader.biHeight;//获取位图高度memDC.SelectObject(bmp);//选中位图对象pDC->StretchBlt(x,y,w,h,        &memDC,0,0,nBmpCX,nBmpCY,SRCCOPY);//在窗口中绘制位图bmp.DeleteObject();//释放位图对象ReleaseDC(pDC);//释放DC

3. 对话框界面设计与绘制的实现:

在对话框重绘的设计与实现过程中,一般需要绘制的对话框区域主要有标题部分、边框部分和客户区部分。具体的区域划分如下图所示。

既然要对多个区域进行位图显示输出,所以我们先封装一个bmp位图显示输出函数如下:

void CClearTmpFileDlg::DisplayBmp(int x,int y,int w,int h,int nID)
{//nID 表示位图资源的ID    CRect winRC;CDC* pDC=GetWindowDC();CDC memDC;memDC.CreateCompatibleDC(pDC);BITMAPINFO bmpInfo;CBitmap bmp;    GetWindowRect(&winRC);bmp.LoadBitmap(nID);bmp.GetObject(sizeof(BITMAPINFO),&bmpInfo);    int nBmpCX = bmpInfo.bmiHeader.biWidth;    int nBmpCY = bmpInfo.bmiHeader.biHeight;memDC.SelectObject(bmp);pDC->StretchBlt(x,y,w,h,        &memDC,0,0,nBmpCX,nBmpCY,SRCCOPY);//在窗口中绘制位图    bmp.DeleteObject();ReleaseDC(pDC);
}

然后就是对各个区域进行位图输出重绘。由于标题栏以及边框主要都是非客户区域绘制,因此应该在WM_NCPAINT 消息中绘制。当然得先通过添加资源的方式将所用到的bmp位图资源导入到项目中。

在 WM_NCPAINT消息对于的 方法OnNcPaint()中调用对话框绘制方法DrawDialog()。该方法的功能就是绘制对话框各个区域的位图。主要代码如下:

void CClearTmpFileDlg::DrawDialog()
{//重绘对话框标题栏、边框、最小化按钮、最大化按钮和关闭按钮等界面m_nFrameCY = GetSystemMetrics(SM_CYFIXEDFRAME);//获取对话框边框的高度m_nFrameCX = GetSystemMetrics(SM_CXDLGFRAME);//获取对话边框的宽度if(GetStyle()&WS_BORDER)//获取对话框是否有边框    {m_nBorderCY = GetSystemMetrics(SM_CYBORDER) + m_nFrameCY;m_nBorderCX = GetSystemMetrics(SM_CXBORDER) +m_nFrameCX; }    else{        m_nBorderCY = m_nFrameCY;m_nBorderCX = m_nFrameCX;}m_nTitleBarCY = GetSystemMetrics(SM_CYCAPTION) + m_nBorderCY;//计算标题栏高度m_nTitleBarCX =m_nBorderCX;CRect winRect,factRect;GetWindowRect(&winRect);factRect.CopyRect(CRect(0,0,winRect.Width(),winRect.Height()));CWindowDC windowsDC(this);//获取窗口设备上下文    //获取整个MFC窗口的高度和宽度m_nWinWidth = winRect.Width();//=781m_nWinHeight = winRect.Height();//=459    //绘制对话框左标题栏位图    DisplayBmp(0,0,100,m_nTitleBarCY,IDB_LEFTTITLE);    //绘制对话框标题栏左端的logo图标DisplayBmp(3,0,26,m_nTitleBarCY,IDB_APPICON);    //绘制对话框右标题栏位图    DisplayBmp(m_nWinWidth-100,0,100,m_nTitleBarCY,IDB_RIGHTTITLE);    //绘制对话框中标题栏位图    DisplayBmp(100,0,m_nWinWidth-200,m_nTitleBarCY,IDB_MIDTITLE);    //绘制对话框左边框位图DisplayBmp(0,m_nTitleBarCY,m_nBorderCX,m_nWinHeight-m_nBorderCY,IDB_LEFTBAR);    //绘制对话框底边框位图DisplayBmp(m_nBorderCX,m_nWinHeight-m_nBorderCX,m_nWinWidth-2*m_nBorderCX,m_nBorderCX,IDB_BOTTOMBAR);    //绘制对话框左边框位图DisplayBmp(m_nWinWidth-m_nBorderCX,m_nTitleBarCY,m_nBorderCX,m_nWinHeight-m_nBorderCY,IDB_RIGHTBAR);    //给对话框绘制最小化按钮DisplayBmp(m_nWinWidth-26*3-5,0,26,26,IDB_MINBTN1);    //给对话框绘制最大化按钮DisplayBmp(m_nWinWidth-26*2-5,0,26,26,IDB_MAXBTN1);    //给对话框绘制关闭按钮DisplayBmp(m_nWinWidth-26-5,0,26,26,IDB_CLOSEBTN1);ReleaseDC(&windowsDC);    //ReleaseDC(&memDC);DrawTitleBarText();//输出标题栏文本}

上面代码中最后的绘制对话框标题文本的方法DrawTitleBarText(),主要是用来显示标题栏的文本,其主要代码如下:

CString strTitle ="小蔡垃圾清理器3.0";
CDC* pDC= GetWindowDC();
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,255,255));
pDC->SetTextAlign(TA_CENTER);
CRect rect;
GetClientRect(&rect);
CSize szText = pDC->GetTextExtent(strTitle);
CFont* font,*fOldFont;
font = new CFont;
font->CreateFont(12,0,0,0,FW_BOLD,FALSE,FALSE,0,ANSI_CHARSET,     OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_SWISS,_T("宋体"));
fOldFont = pDC->SelectObject(font);
pDC->TextOut(100,6.5,strTitle,18);
pDC->SelectObject(fOldFont);
ReleaseDC(pDC);

在完成对话框相应区域的位图后,并没有完成任务,还需要处理标题栏按钮的热点效果,以及按钮的单击事件。首先得处理鼠标在非客户区域移动时的事件,即WM_NCMOUSEMOVE消息,在其消息处理函数中判断当前的鼠标点是否位于标题栏的按钮区域,如果是则设置按钮的热点效果,并且记录当前的按钮状态,及鼠标点在哪个按钮上。同样的,处理对话框非客户区域的单击事件,即WM_NCLBUTTONDOWN消息,在其消息处理函数中完成单击事件操作。这部分的代码比较简单,在此不予显示。

4.按钮控件UI界面设计与实现

在MFC下编程,很多时候对于标准的按钮控件不是很满意,想要弄的美观些。这就需要按钮重绘。重绘按钮一般的实现方法就是重写CButton类。

首先给工程添加一个自绘按钮类MyDrawButton,基类为CButton。要想让按钮具备自绘功能,就要为按钮添加BS_OWNERDRAW属性。为类CButton重载PreSubclassWindow虚函数。在该函数中添加如下一行代码:

SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);

当按钮控件具有了自绘功能之后,每次控件状态改变都会触发DrawItem函数,在该函数中来绘制按钮的形态外观,所以第二步就要重载DrawItem虚函数。在这个函数中就可以自由发挥了,比如绘制背景,底色,按钮标题,绘制文本字体样式等等。

一般都会为按钮定义几种不同状态时的外观,比如光标滑过时的状态,按钮按下时的状态,按钮禁用时的状态,以及按钮的正常状态等等。这就要为新的按钮添加几种重要的消息响应。比如WM_MOUSELEAVE消息,WM_MOUSEHOVER消息和WM_MOUSEMOVE消息等等,值得一提的是前两个消息的响应函数需要自己手动添加,微软提供了一个TrackMouseEvent函数在光标离开一个窗口时投递WM_MOUSELEAVE消息,光标滑过窗口时投递WM_MOUSEHOVER消息。一般来说可以在WM_MOUSEMOVE消息响应函数中调用TrackMouseEvent函数来投递WM_MOUSELEAVE消息和WM_MOUSEHOVER消息。然后在WM_MOUSELEAVE消息的响应函数中标记“光标已经离开按钮”,然后调用InvalidateRect函数让按钮重绘。在WM_MOUSEHOVER消息的响应函数中标记“光标正在按钮上方”,并调用InvalidateRect函数让按钮重绘。

在本文中,重绘按钮分为3个部分。

(1)绘制按钮背景样式,即绘制背景bmp位图,使得按钮具有自定义的样式,同时在绘制按钮背景的输出位图时采用TransparentBlt()函数,该函数的作用是使窗体上显示位图的背景与窗体背景色融为一体,不仅可以显示按钮bmp位图样式,而且还可以使背景透明。

(2)就是绘制按钮上的文本。主要绘制按钮上文本的样式,包括字体大小,字体样式,字体颜色等属性。

(3)实现不同状态下的按钮的外观样式,主要包括WM_MOUSEMOVE和WM_MOUSELEAVE两个消息的消息处理函数。分别实现鼠标在按钮区域上和不在按钮区域上的状态。为了标记鼠标移动到按钮区域内停留,需要用到一个定时器来标记鼠标是否还在按钮区域内停留。在WM_MOUSEMOVE内启动定时器,触发WM_MOUSELEAVE消息时结束定时器即销毁定时器。定时器的主要代码如下:

void MyDrawButton::OnTimer(UINT_PTR nIDEvent)
{    // TODO: 在此添加消息处理程序代码和/或调用默认值if(nIDEvent != 24)        return;CPoint    point;CRect    rect;GetWindowRect(&rect);    GetCursorPos(&point);    // 如果鼠标离开按钮区域,重绘按钮if (!rect.PtInRect(point) && m_bMove){KillTimer (24);m_DrawState=ST_MOVEOUT;m_bMove=FALSE;Draw();}CButton::OnTimer(nIDEvent);
}

重绘按钮类MyDrawButton的主要实现代码如下:

定义的一些重绘用到的变量:

#define ST_MOVEIN        0//绘制状态—在按钮区域上#define ST_MOVEOUT        1 //绘制状态—不在按钮区域上int m_DrawState;//绘制状态    int m_nBmpID;//当前显示的背景bmp位图的资源IDbool m_bMove;//鼠标是否进入按钮区域COLORREF m_clText;//当前文本颜色COLORREF m_clActiveText;//鼠标进入按钮区域时文本颜色COLORREF m_clNormalText;//鼠标离开按钮区域时文本颜色

消息处理函数和定义的函数以及实现:

void MyDrawButton::PreSubclassWindow()
{SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW);
}void MyDrawButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{Draw();//绘制按钮}void MyDrawButton::Draw()//绘制按钮{DrawBackground();//绘制按钮bmp位图,并使背景透明化DrawText();//绘制按钮上的文本}void MyDrawButton::DrawText()
{//绘制按钮上的文本的字体大小、样式等    CString        itemString;CRect  clientRect;CClientDC  dc(this);GetClientRect(&clientRect);GetWindowText(itemString);    if(itemString){CSize size=dc.GetTextExtent (itemString);//获得所选字体中指定字符串的高度和宽度int rectwidth=clientRect.Width();        int rectheight=clientRect.Height();        int textwidth=size.cx ;        int textheight=size.cy ;        int x,y; // 文本的位置        // 计算文本的输出位置x=(rectwidth-textwidth)/2;//水平居中y=(rectheight-textheight)/2;//垂直居中            switch(m_DrawState){        case ST_MOVEIN://鼠标进入按钮区域m_clText=m_clActiveText;            break;        case ST_MOVEOUT://鼠标离开按钮区域m_clText=m_clNormalText;            break;        default:m_clText=m_clNormalText;            break;}dc.SetTextColor(m_clText);dc.SetBkMode(TRANSPARENT);CFont *font ;font =new CFont();        int fontSize = 14;        font->CreateFont(fontSize,0,0,0,FW_BOLD,FALSE,FALSE,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_SWISS,_T("宋体"));dc.SelectObject(font);dc.TextOut (x,y,itemString);}
}void MyDrawButton::SetBkBmp(int nBmpID)
{//设置按钮bmp位图样式m_nBmpID = nBmpID;
}void MyDrawButton::DrawBackground()
{//绘制按钮bmp位图,并使背景透明化    CRect winRC;CDC* pDC=GetWindowDC();CDC memDC;memDC.CreateCompatibleDC(pDC);BITMAPINFO bmpInfo;CBitmap bmp;    GetWindowRect(&winRC);bmp.LoadBitmap(m_nBmpID);bmp.GetObject(sizeof(BITMAPINFO),&bmpInfo);    int nBmpCX = bmpInfo.bmiHeader.biWidth;    int nBmpCY = bmpInfo.bmiHeader.biHeight;memDC.SelectObject(bmp);pDC->TransparentBlt(0,0,nBmpCX,nBmpCY,&memDC,0,0,nBmpCX,nBmpCY,RGB(14,94,157));//在窗口中绘制位图,RGB(14,94,157)是透明色    bmp.DeleteObject();ReleaseDC(pDC);
}

到此,按钮的自定义重绘完成了,接下来就可以使用自己重绘的按钮类MyDrawButton了。首先往对话框中添加一个按钮控件(以立即扫描按钮为例),假设它的ID值为IDC_TEST。进入类向导(Class Wizard)的成员变量属性页,为IDC_ BEGIN添加一个变量m_btnBegin。如下:

MyDrawButton m_btnBegin;

然后就可以调用MyDrawButton的方法来设置按钮的样式了。如下:

m_btnBegin.SetBkBmp(IDB_BTN210x95,IDB_BTN210x95_3);//IDB_BTN210x95,IDB_BTN210x95分别为默认位图和鼠标在按钮区域时的位图。

到现在为止,按钮类的重绘完成了,可以随意定义自己喜欢的样式的按钮了。现在相对完善成形的一个垃圾清理工具软件就开发完了。

三、运行效果

最后软件的主要成果界面如下:

软件打开准备就绪界面

正在运行截面图

扫描完成界面图:

清理完成界面图

四、项目结构图

这里补上,项目代码结构图

项目结构图

代码下载:http://www.demodashi.com/demo/13430.html

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

Windows 开发之VC++垃圾清理程序软件相关推荐

  1. C++打造Windows优化大师系统,自制的垃圾清理程序它不香吗?

    本程序软件的主要实现垃圾文件清理的功能,即对指定的文件格式的临时文件或垃圾文件进行遍历.扫描.显示.删除清理等功能.在程序界面设计方面,对默认对话框重新自定义绘制,主要包括标题栏的重绘.对话框边框的重 ...

  2. c++整人代码,“垃圾清理程序”

    如果你朋友耍了你... 可以把这个在他(她)的电脑上运行这个... #include<cmath> #include<cstring> #include<iostream ...

  3. CDR插件开发之Application(应用程序)

    在CorelDRAW提供的对象模型中,Application是被开发者经常使用的一个对象,也是最顶级的对象.本文对CorelDRAW(以下简称CDR)对象模型中的 Application 类做了一个简 ...

  4. Android开发之APP打开小程序后小程序无法返回APP,无法打开APP,launchApp无法返回app的原因

    Android打开小程序可以看我上篇文章介绍:Android打开小程序 我这边已经成功打开小程序了参数也传递过去了,现在就是无论如何点击返回APP都没有反应,也没用走微信页面WXEntryActivi ...

  5. Android开发之APP唤醒小程序,打开小程序,调起小程序以及传参数的实现方法(附加源码)

    老套路咱们先看效果图: 可以先看下官方文档介绍:微信官方文档APP打开小程序链接 我这边打开了,上面奔溃是因为模拟器不兼容的原因: 主要讲解下打开小程序核心代码: // 填应用AppIdString ...

  6. Android插件化开发之AMS与应用程序(客户端ActivityThread、Instrumentation、Activity)通信模型分析

    转载来自:http://blog.csdn.net/qinjuning/article/details/7262769 今天主要分析下ActivityManagerService(服务端) 与应用程序 ...

  7. iPhone控制Windows开关机,启动关闭程序等

    整体思路是利用第三方平台,传递CMD的相关命令,然后Windows获取后执行就行了. 去巴法科技&巴法云-巴法设备云-巴法物联网云平台注册一个账户,控制台添加一个项目,然后记录下名称.左上角有 ...

  8. Liferay7 BPM门户开发之24: Liferay7应用程序安全

    整理中...... Resources, Roles, and Permissions Portal Access Control List (PACL) Custom SSO Providers A ...

  9. 安卓手机主题软件_安卓手机垃圾清理软件!推荐必备!

    哈喽,大家好!我是大熊啊!说到手机垃圾清理软件,大家并不陌生,毕竟大家手机内存有限,大量的软件垃圾会占用宝贵的存储空间.所以有很大部分的人都会在手机上安装一个垃圾清理软件,像什么360清理 ,安全管家 ...

最新文章

  1. Selenium 显式等待条件及其含义
  2. node服务的监控预警系统架构 1
  3. 《剑指offer》面试题20——顺时针打印矩阵(C++)
  4. 深入理解Nacos源码注册中心之服务发现(订阅拉取)
  5. 【leetcode】力扣算法:杨辉三角 java语言解题
  6. 百度搜索风云榜Rss
  7. 学计算机的逻辑学博士,逻辑学博士点
  8. php 根据身份证计算年龄
  9. LabVIEW如何开发大型程序
  10. 如何量个量化策略的好坏
  11. redis expire命令
  12. java h5在线音频_html5 mp3音频播放代码网页在线录音
  13. matlab做机器人运动轨迹,matlab机器人工具箱学习笔记——机器人的运动轨迹
  14. SQL语句---创建表
  15. 音乐服务器制作教程,让NAS做音乐服务器
  16. 使用AFNetWorking读取JSON出现NSCocoaErrorDomain Code=3840的解决方法
  17. STM32F030使用硬件SPI与字库芯片通信
  18. 最简单的uefi和legacy介绍和举例(可能吧?)
  19. python-opencv实现图像超像素分割(SLIC、SEEDS、LSC)
  20. 零基础学python要多久?

热门文章

  1. 组建无线网络的六条思路
  2. 整理了一系列的JavaScript树操作方法,不用再一遍又一遍的百度了
  3. python新式类和旧式类区别
  4. OC开发之——OC简介(1)
  5. 【leetcode-DFS】求根节点到叶节点数字之和/二叉树的最大路径和/路径总和/左叶子之和/树的直径
  6. java 实现树形结构
  7. 安装docker报错:Error: Unknown command: cask
  8. 《游戏开发者》调查:iOS和Unity是游戏开发者的最爱
  9. 系统(层次)聚类法及Spss实现
  10. 耿明雨出席2021深圳国际珠宝展览会