您好,欢迎来到五一七教育网。
搜索
您的当前位置:首页VC编程技巧

VC编程技巧

来源:五一七教育网
VC编程技巧

MFC 技巧90例--总结篇(三) 2007-03-07 14:00

21. 介绍函数过程中一种任意键退出同时能处理消息的实现方法 1. 设置定时器,用于使::GetMessage(...)函数总能快速取到消息. 2. 在函数处理中加入:

函数每执行完一步后执行下面的代码. if (::GetMessage(&msg, 0, 0, 0)) {

if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) return ;

::TranslateMessage(&msg); ::DispatchMessage(&msg); }

else ::PostQuitMessage(0); 22. 如何隐藏工具栏 添加如下两个函数 隐藏:

void CMainFrame::OnHide() {

if(m_wndToolBar.IsWindowVisible()) m_wndToolBar.ModifyStyle(WS_VISIBLE,0); SendMessage(WM_SIZE); } 显示:

void CMainFrame::OnShow() {

if(!m_wndToolBar.IsWindowVisible()) m_wndToolBar.ModifyStyle(0,WS_VISIBLE);

SendMessage(WM_SIZE); }

23. 如何动态获取工具条指针并给工具条加标题? [问题提出]

工具条也是窗口,是窗口就有标题,如何给工具条加标题? [程序实现]

不想动态改变工具条的标题就在CMainFrame::OnCreate()中: int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { ......

m_wndToolBar.SetWindowText(_T(\"Standdard\")); return 0; }

若想动态改变工具条的标题,如下:

声明一个菜单,并响应事件,如响应:OnMyToolBar()函数 void CMainFrame::OnMyToolBar() {

// TODO: Add your command handler code here CToolBar AR);

pToolBar->SetWindowText (_T(\"Standdard\")); }

不要在TooBar悬浮时做OnMyToolBar()会出错的. 顺便提一下如何获得状态条的指针: CStatusBar TUS_BAR);

24. 在状态条中显示鼠标的设备坐标与逻辑坐标

显示器的设备坐标系的原点在客户区的左上角,x轴向右增长,y

*

pStatusBar

=(CStatusBar

*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STA

*pToolBar

=

(CToolBar

*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLB

轴向下增长。我们要设置的逻辑坐标系的原点则在客户区的中心,x轴向右增长,y轴向上增长,如一个笛卡尔坐标系一般。

为CChildView添加一个成员函数void OnPrepareDC(CDC * pDC, CPrintInfo * pInfo = NULL);

void OnPrepareDC(CDC * pDC, CPrintInfo * pInfo){ CRect rect;

// 设置映射模式为LOMETRIC (0.1mm),右上为增长方向 pDC->SetMapMode (MM_LOMETRIC); // 将坐标原点定在客户区的中心 GetClientRect(rect);

pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2); }

为CChildView响应鼠标移动消息,并在状态条中显示鼠标的坐标值。m_ptMouse数据成员是原打算做十字交叉线用的,在此使用没有实际意义。

void CChildView::OnMouseMove(UINT nFlags, CPoint point){ CClientDC dc(this); CString str;

OnPrepareDC(&dc);

//要访问类CMainFrame,需要将mainfrm.h文件引入 CMainFrame

*

pFrame

=

(CMainFrame

*)

AfxGetApp()->m_pMainWnd;

//要访问CMainFrame的数据成员m_wndStatusBar,需要手工修改mainfrm.h,public这个数据成员

CStatusBar

*

pStatus

=

(CStatusBar

*)

&pFrame->m_wndStatusBar;

m_ptMouse = point;

str.Format (\"设备坐标X=%i pixel, Y=%i pixel\m_ptMouse.y);

pStatus->SetPaneText(1, str);

dc.DPtoLP(&m_ptMouse);

str.Format (\"逻辑坐标X=%i * 0.1mm, Y=%i * 0.1mm\m_ptMouse.x, m_ptMouse.y);

pStatus->SetPaneText(2, str); }

25. 如何用VC++ 动态修改应用程序菜单 [问题提出]

本文将介绍一些使用CMenu的方法,如查找指定菜单,在指定选项前添加菜单项.....

[解决方法]

使用CWnd::GetMenu( )访问主菜单,GetMenu( )返回指向CMenu对象的指针,它有一些成员函数,允许我们修改一个菜单。

1) 如何实现找到一个菜单项: 步骤如下: {

//动态修改菜单: // Get the Main Menu

CMenu* pMainMenu = AfxGetMainWnd()->GetMenu(); CMenu* pSubMenu = NULL; int i;

for (i=0; i<(int)pMainMenu->GetMenuItemCount(); i++) {

pSubMenu = pMainMenu->GetSubMenu(i);

if (pSubMenu && pSubMenu->GetMenuItemID(0) == ID_FILE_NEW)

break; }

CString s;

s.Format(\"%d\菜单项的位数. AfxMessageBox(s);

ASSERT(pSubMenu); }

2) 动态编辑菜单:

步骤如下(可以用上例的pSubMenu,要加的菜单你自己定义.): 1) 添加一个称为Wzd2,命令ID为IDC_NAME_NEW1的菜单命令到该菜单中,可以用:

pSubMenu->AppendMenu(0,IDC_NAME_NEW1,\"New&1\"); 2) 在New1前插入New2,可以用:

pSubMenu->InsertMenu(IDC_NAME_NEW1,MF_BYCOMMAND,IDC_NAME_NEW2, \"New&2\");

3) 把New1改变成New3,可以用:

pSubMenu->ModifyMenu(IDC_NAME_NEW1,MF_BYCOMMAND,IDC_NAME_NEW3, \"New&3\");

4) 删除该菜单中第二项,可以用:

pSubMenu->RemoveMenu(1,MF_BYPOSITION); 26. VC++中的3D按钮的编程

运行AppWizard生成一个基于对话框的test工程,在对话框中加入一个CButton控件。在CButton 控件的General属性页将控件的ID改为IDC_3DTEXTBTN,Caption改为“谁与争疯”,在控件Styles 属性页选中OwnerDraw,其余设置保持默认。

用classwizard创建一个新类:C3dTextButton,基类为CButton。为C3dTextButton类添加一个protected的函数void Draw(CDC* pDC, const CRect& rect, UINT state)。如下所示编写代码:void C3dTextButton::Draw(CDC *pDC, const CRect &rect, UINT state)

{

CString text; GetWindowText(text); int l=text.GetLength(); CRect rectClient=rect; //获得控件的字体 CFont* pFont=GetFont();

//确定所选字体有效高度和宽度 LOGFONT logfont;

pFont->GetObject(sizeof(LOGFONT),&logfont); if(logfont.lfHeight==0)logfont.lfHeight=20; logfont.lfWidth=0;//宽度设为0,宽度值由高度确定 logfont.lfWeight=1000;

logfont.lfEscapement=logfont.lfOrientation=0;

CFont tryfont; VERIFY(tryfont.CreateFontIndirect(&logfont)); CFont* pFontOld=pDC->SelectObject(&tryfont); //根据控件大小,调整字体的高度,使文本与控件协调 CSize textSizeClient=pDC->GetTextExtent(text,l);

if(rectClient.Width()*textSizeClient.cy>rectClient.Height()*textSizeClient.cx)

{

logfont.lfHeight=::MulDiv(logfont.lfHeight,rectClient.Height(),textSizeClient.cy); }

else{

logfont.lfHeight

= ::MulDiv(logfont.lfHeight,rectClient.Width(),textSizeClient.cx); }

//创建并选择协调后的字体

CFont font; font.CreateFontIndirect(&logfont); pDC->SelectObject(&font);

textSizeClient=pDC->GetTextExtent(text,l); //确定文本与控件边界的距离minx,miny int

textSizeClient.cx)/2;

int

textSizeClient.cy)/2;

int oldBkMode=pDC->SetBkMode(TRANSPARENT); COLORREF textcol=::GetSysColor(COLOR_BTNTEXT);

miny=rectClient.top+(rectClient.Height()-minx=rectClient.left+(rectClient.Width()-

COLORREF oldTextColor=pDC->SetTextColor(textcol); int cx = minx; int cy = miny;

int s=(state&ODS_SELECTED)?-1:+1; cx+= 3; cy+= 3; //实现3D效果

pDC->SetTextColor(::GetSysColor(COLOR_3DDKSHADOW)); pDC->TextOut(cx-s*2,cy+s*2,text); pDC->TextOut(cx+s*2,cy-s*2,text); pDC->TextOut(cx+s*2,cy+s*2,text);

pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT)); pDC->TextOut(cx+s*1,cy-s*2,text); pDC->TextOut(cx-s*2,cy+s*1,text); pDC->TextOut(cx-s*2,cy-s*2,text);

pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW)); pDC->TextOut(cx-s*1,cy+s*1,text); pDC->TextOut(cx+s*1,cy-s*1,text); pDC->TextOut(cx+s*1,cy+s*1,text);

pDC->SetTextColor(::GetSysColor(COLOR_3DLIGHT)); pDC->TextOut(cx,cy-s*1,text); pDC->TextOut(cx-s*1,cy,text); pDC->TextOut(cx-s*1,cy-s*1,text); pDC->SetTextColor(textcol); //输出标题

pDC->TextOut(cx,cy,text); //恢复设备描述表

pDC->SetTextColor(oldTextColor); pDC->SetBkMode(oldBkMode); pDC->SelectObject(pFontOld); }

用classwizard重载C3dTextButton类的DrawItem函数。编写代码如下所示:

void {

CDC* pDC=CDC::FromHandle(lpDrawItemStruct->hDC); ASSERT_V ALID(pDC);

CRect rectClient=lpDrawItemStruct->rcItem; Draw(pDC,rectClient,lpDrawItemStruct->itemState); }

用classwizard为IDC_3DTEXTBTN建立一个C3dTextButton控件变量m_3dTextButton1。

把“3dTextButton.h”加入testDlg头文件。编译并测试应用程序。

27. 如何正确的得到ComBox的指针 CComboBox CComboBox

*mComb *mComb

= =

(CComboBox*)GetDlgItem(IDC_DuanCB);

(CComboBox*)::GetDlgItem(m_hWnd,IDC_DuanCB);

28. 如何让对话框中的CEdit控件类接收对话框的消息 //////////////////////////////////////////////// // 如何让对话框中的CEdit控件类接收对话框的消息 ////////////////////////////////////////////////

1、在对话框中增加一个ID 为IDC_EDIT1的CEdit1控件 2、通过ClassWizard 生成一个基于CEdit的新类CMyEdit, CMyEdit m_wndEdit;

3、在对话框OnInitDialog()中,将m_wndEdit子类化,使其能够接受对话框的消息。

m_wndEdit.SubclassDlgItem (IDC_EDIT1,this);

29.利用WM_CTLCOLOR消息实现编辑控制(Edit Control)的

C3dTextButton::DrawItem(LPDRAWITEMSTRUCT

lpDrawItemStruct)

文本与背景色的改变

首先要明白:WM_CTLCOLOR是一个由控制(Control)发送给它父窗口的通知消息(Notification message)。

实现步骤:

生成一个标准的单文档应用程序框架,假设应用程序的名称为Color。我将利用它的About对话框做示范。在About dialog中添加两个Edit control,设定其ID为IDC_EDIT1与IDC_EDIT2。

第一种方法(对应于IDC_EDIT1): 按照标准的Windows编程,由其父窗口的消息处理函数负责处理WM_CTLCOLOR消息。

1. 在CAboutDlg中添加一个数据成员:HBRUSH m_brMine; 2. 利用向导映射AboutDlg的WM_CTLCOLOR消息,产生函数:HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);

pDC是AboutDlg的设备上下文,pWnd是AboutDlg中发送该消息的control指针,nCtlColor市Control的类型编码。对其进行如下修改:

HBRUSH CAboutDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)

{

if ((pWnd->GetDlgCtrlID() == IDC_EDIT1) && (nCtlColor == CTLCOLOR_EDIT))

{

COLORREF clr = RGB(255,0,0);

pDC->SetTextColor(clr);//设置红色的文本 clr = RGB(0,0,0);

pDC->SetBkColor(clr);//设置黑色的背景 m_brMine = ::CreateSolidBrush(clr);

return m_brMine;//作为约定,返回背景色对应的刷子句柄 } else

{

HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); return hbr; } }

第二种方法(对应于IDC_EDIT2):

利用MFC 4.0的新特性: Message reflection。 1.利用向导添加一个新的类:CColorEdit,基类为CEdit; 2.在CColorEdit中添加一个数据成员: HBRUSH m_bkBrush; 3.利用向导映射CColorEdit的\"=WM_CTLCOLOR\"消息,产生函数:

HBRUSH CColorEdit::CtlColor(CDC* pDC, UINT nCtlColor); 对其进行如下修改:

HBRUSH CColorEdit::CtlColor(CDC* pDC, UINT nCtlColor) {

COLORREF clr = RGB(0,0,0);

pDC->SetTextColor(clr);//设置黑色的文本 clr = RGB(255,0,0);

pDC->SetBkColor(clr);//设置红色的背景 m_bkBrush = ::CreateSolidBrush(clr);

return m_bkBrush;//作为约定,返回背景色对应的刷子句柄 }

4.利用向导为IDC_EDIT2生成一个数据成员CColorEdit m_coloredit;

5.在定义CAboutDlg的color.cpp文件中加入:#include \"coloredit.h\"

30. 如何防止密码被非法获取? [问题提出]

这两天大家比较专注在获取Edit密码框的密码.在盗取时,我们如何防范呢?

[解决方法]

此方法针对于通过SendMessage向此窗口发送WM_GETTEXT或EM_GETLINE消息来取得密码.跟我来.

[程序实现]

方法很简单,用CWnd::DefWindowProc函数拦截得到的消息(向Edit发的).

建立名为My的对话框工程.建立一个Edit控件ID=IDC_EDIT1.建一个新类名为CMyProtectEdit,派生于CEdit.

在MyDlg.cpp中声明全局变量:BOOL g_bIdentity; BOOL g_bIdentity; 在MyProtecEdit.cpp中: extern BOOL g_bIdentity;

响应CMyProtectEdit的DefWindowProc函数:

LRESULT CMyProtectEdit::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

// TODO: Add your specialized code here and/or call the base class

// 对Edit的内容获取必须通过以下两个消息之一,不对其采用默认的处理:

if(( message == WM_GETTEXT) || ( message == EM_GETLINE)) {//检查是否为合法 if(!g_bIdentity)

{//非法获取,显示非法信息

AfxMessageBox(_T(\"不能让你看我的密码,:( !\")); return 0; )

g_bIdentity = FALSE;//合法获取 }

return CEdit::DefWindowProc(message, wParam, lParam);

}

然后在MyDlg.cpp中

void CMyDlg::DoDataExchange(CDataExchange* pDX) {

CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CGetPasswordDlg)

// NOTE: the ClassWizard will add DDX and DDV calls here if( pDX->m_bSaveAndValidate) {

g_bIdentity = TRUE; }

//}}AFX_DATA_MAP MFC 技巧90例--总结篇(五) 2008-02-03 14:35

51. 如何获得其他程序的图标,并显示在View中 [问题提出]

有的时候,如:类资源管理器会遇到获得程序图标并显示的操作,如何实现呢?

[解决方法]

SDK函数SHGetFileInfo来获得有关文件的很多信息:如大小图标,属性,类型等.

[程序实现]

建立名为My的SDI工程.在OnPaint()函数中加入: void CMyView::OnPaint() {

CPaintDC dc(this); // device context for painting HICON

if (hIcon && hIcon!=(HICON)-1) dc.DrawIcon(10,10,hIcon);

hIcon=::

ExtractIcon(AfxGetInstanceHandle(),_T(\"NotePad.exe\"),0);

// TODO: Add your message handler code here // Do not call CView::OnPaint() for painting messages }

说明:_T(\"NotePad.exe\")指的是要获得什么程序的图标.

或者在OnDraw()中(此时必须保证没有OnPaint()函数,想想为何?) void CMyView::OnDraw(CDC* pDC) {

CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc);

// TODO: add draw code for native data here HICON

if (hIcon &&hIcon!=(HICON)-1) pDC->DrawIcon(10,10,hIcon); }

52 .RichEdit

在Dialog(FormView中打开)中加入CRichEdit控件后,这个dialog 为什么打不开如何处理?

[解决方法]

在函数:InitInstance的第一句加入AfxInitRichEdit(); 53. 如何使FormView中显示dialog时,不是凹的? [问题提出]

为什么FormView中显示dialog时,是凹的,能不能不这样 [解决方法]

在Dialog的属性中:

增加属性WS_BORDER或者WS_EX_WINDOWEDGE 用程序实现:

pView->ModifyStyle(,WS_BORDER) 口标题?

pView->ModifyStyleEx(,WS_EX_WINDOWEDGE ) 54. 如何改变窗

hIcon=::

ExtractIcon(AfxGetInstanceHandle(),_T(\"NotePad.exe\"),0);

[问题提出]

在应用程序的不同运行时期,要反映当前状态往往会修改应用程序标题.

[解决方法]

在MFC类库中提供了CWnd::SetWindowText函数,通过该函数可以改变任何窗体(包括控件)的标题.

改变主窗体的标题: CWnd *m_pMainWnd;

m_pMainWnd=AfxGetMainWnd();

m_pMainWnd->SetWindowText(_T(\"改变标题\")); 当改变多视MDI的子窗口的标题时,用:

GetParentFrame()->SetWindowText(_T(\"MDI Child改变标题\"));

当改变按钮的标题时(假设按钮的ID=IDC_BUTTON1):

GetDlgItem(IDC_BUTTON1)->SetWindowText(_T(\"Button 改变标题\"));

运行看看. 55.图标透明

(1).Windows中的图标其实是有两个图像组成的,其中一个用于与它要显示的位置的图像做“AND”操作,另一个作“XOR”操作。

透明:用“白色”AND,用“黑色”XO R 反色:用“白色”AND,用“白色”XOR 正常色:用“黑色”AND,用正常颜色XOR. (2). WIN9X中好像是对像素的操作实现透明的 WIN2K中就有API直接实现透明了! WIN2K中 GetWindowLong SetWindowLong

SetLayeredWindowAttributes 三个API就可以实现透明了!

(3)

::DrawIconEx(pDC->GetSafeHdc(),point.x,point.y,icon,icosize,icosize,0,NULL,DI_NORMAL);

56.ASSERT()是干什么用的

ASSERT()是一个调试程序时经常使用的宏,在程序运行时它计算括号内的表达式,如果表达式为FALSE (0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。这个宏通常原来判断程序中是否出现了明显非法的数据,如果出现了终止程序以免导致严重后果,同时也便于查找错误。例如,变量n在程序中不应该为0,如果为0可能导致错误,你可以这样写程序:......

ASSERT( n != 0); k = 10/ n; ......

ASSERT只有在Debug版本中才有效,如果编译为Release版本则被忽略。

assert()的功能类似,它是ANSI C标准中规定的函数,它与ASSERT的一个重要区别是可以用在Release版本中。

56. 将RADIO控件初始状态设置成为选中

1、\"在OnInitialDialog中用CButton::CheckRadioButton(...) 2、\"在OnInitialDialog中用CButton::SetCheck(...) 3、\"关联一个整型值,在构造函数中设为0。 57.获得视图 CFrameWnd* CMyView*

58.如何得到屏幕的真实尺寸 [问题提出]

我的屏幕是1024*800,如何得到屏幕的真实大小,我用GetSystemMetrics(SM_CYFULLSCREEN)得到的高度总是小于800

pFrameWnd pView

= =

(CFrameWnd*)theApp.GetMainWnd(); (CMyView*)pFrameWnd->GetActiveView();

[问题解答]

GetSystemMetrics(SM_CYFULLSCREEN)得到的只是屏幕用户区的大小。要得到屏幕的真实大小需要使用

GetDeviceCaps函数,该API函数原型是这样的: int GetDeviceCaps( HDC hdc,// handle to DC int nIndex// index of capability );

///得到屏幕尺寸的代码如下 void CMyDlg::OnPaint() {

CPaintDC dc(this);

int cx = ::GetDeviceCaps(dc.m_hDC,HORZRES);///得到宽度 int cy = ::GetDeviceCaps(dc.m_hDC,VERTRES);///得到高度 CDialog::OnPaint(); 59. 修改标题栏高度 NONCLIENTMETRICS nm 调重

用设

SystemParametersInfoSystemParametersInfo

(SPI_GETNONCLIENTMETRICS,sizeof(nm),&nm,0) (SPI_SETNONCLIENTMETRICS,sizeof(nm),&nm,0)

60. 如何实现“气球式”工具提示。

本程序介绍一个与CToolTipCtrl相似的类CTooolTipWnd。 使用该类的方法如下:

1. 增加ToolTipWnd.cpp到工程文件。 2. 在头文件中添加#include \"ToolTipWnd.h\" 。 3. 在类声明中添加:

CToolTipWnd m_BalloonToolTip;

4. 在OnInitDialog(对话框)或OnInitialUpdate(表单视)中添加下面代码:

m_BalloonToolTip.Create(this);

m_BalloonToolTip.AddTool(GetDlgItem(), , [text color]); eg.

m_BalloonToolTip.AddTool(GetDlgItem(IDC_EDIT1),\"Tooltip\RGB(255,0,0));

第三个参数为可选,缺省为RGB(0, 0, 0)。缺省文本颜色可以用SetDefTextColor进行设置。

4. 重载PreTranslateMessage并添加下面代码: if(m_BalloonToolTip)

m_BalloonToolTip.RelayEvent(pMsg); 61. dlg 上建立View的方法: OnInitDialog() {

CDialog:;OnInitDialog(); CRect rectWindows;

GetWinodwRect(&rectWindows);

CRuntimeClass *pViewClass=RUNTIME_CLASS(CXXXView); CCreateContext *pContext=new CCreateContext; pContext->m_pCurrentDoc=NULL; pContext->m_pCurrentFrame=NULL; pContext->m_pLastView=NULL;

pContext->m_pNewDocTemplate=NULL; pContext->m_pNewViewClass=pViewClass; CWnd

*pWnd=DYNAMIC_DOWNCAST(CWnd,pviewClass->CreateObject());

pWnd->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW,CRect(0,0,0,0),this,pContext);

delete pContext; CXXXView

*pView=DYUNAMIC_DOWNCAST(CXXXView,pWnd); ...............

}

62. 窗口最大化、最小化及关闭的消息是什么?如何截获? 最大化、最小化将发送WM_SYSCOMMAND消息。要处理该消息,可以这么做:

1、在Form的头文件中添加:

void __fastcall RestrictMinimizeMaximize(TMessage &Msg); BEGIN_MESSAGE_MAP

MESSAGE_HANDLER(WM_SYSCOMMAND, RestrictMinimizeMaximize)

END_MESSAGE_MAP(TForm) 2、在Form的单元文件中添加: void

TForm1::RestrictMinimizeMaximize(TMessage& Msg)

{

if (Msg.WParam == SC_MINIMIZE) {

//catches minimize... }

else if (Msg.WParam == SC_MAXIMIZE) {

//catches maximize... }

TForm::Dispatch(&Msg);

// or \"else TForm::Dispatch(&Msg)\" to trap }

关闭窗口的消息为WM_CLOSE,C++Builder提供了OnClose事件。

63. 如何遍历整个目录树查找文件

在应用程序的开发过程中,会遇到如何查找某一文件以确定此文

__fastcall TMessage,

件路径的问题。利用CFileFind

类可以比较方便地在当前目录下进行文件查找,但却不能对其子目录中的文件进行搜寻。而实际应用中往往需要对某一整个目录树,甚至是整个C盘或D盘驱动器进行文件搜寻。通过实践,我们在Visual C++ 6.0中编程实现了如何遍历任意目录树,以查找某一特定的文件。

在下面的具体陈述中可以看到,在确定要查找的文件名和要进行搜索的目录的名称后,将调用函数Search_Directory进行文件的查找。首先依次查找当前目录下的每一个实体(文件或是子目录),如果是某一子目录,则进入该子目录并递归调用函数Search_Dirctory进行查找,查找完毕之后, 再返回上一级目录;如果不是子目录而是某一文件,则判断其是否就是我们要查找的文件,如果是则输出其完整的文件路径。这样,通过Search_Directory函数的反复递归调用,就可以实现对整个目录,包括子目录的遍历搜索。下面将举例详细讲述如何在VC++中编程实现在整个目录树中的文件查找。

1.在Visual C++ 6.0(VC++ 5.0与之类似)中用默认方式创建了一基于对话框的应用程序Search。在主窗口对话框上放置一命令按钮,其Caption为“Search File”,ID为ID_BUTTON_SEARCH。单击此按钮将完成文件的查找工作。

2.利用ClassWizard为“Search File”按钮的BN_CLICKED 事件添加处理函数OnButtonSearch,代码如下:

#include 〈direct.h〉 #include 〈io.h〉

void CSearchDlg::OnButtonSearch() {

// TODO: Add your control notification handler code here char szFilename[80];

// 字符串szFilename 表示要查找的文件名 strcpy(szFilename,\"Mytext.txt\");

_chdir(\"d:\\\\\"); // 进入要查找的路径(也可为某一具体的目录)

// 查找文件, 如果查到则显示文件的路径全名 Search_Directory(szFilename); // 为CSearchDlg类的一成员函数 MessageBox(″查找文件完毕!″); // 显示查找完毕的信息 }

3. 在CSearchDlg类中增加成员函数Search_Directory,它将完成具体的文件查找工作,代码如下:

void CSearchDlg::Search_Directory(char* szFilename) {

long handle;

struct _finddata_t filestruct; //表示文件(或目录)的信息 char path_search[_MAX_PATH]; //表示查找到的路径结果

// 开始查找工作, 找到当前目录下的第一个实体(文件或子目录), // \"*\"表示查找任何的文件或子目录, filestruct为查找结果 handle = _findfirst(\"*\

// 如果handle为-1, 表示当前目录为空, 则结束查找而返回 if((handle == -1)) return;

// 检查找到的第一个实体是否是一个目录(http://www..com/doc/9c14237945.html,为其名称)

if( ::GetFileAttributes(http://www..com/doc/9c14237945.html,) & FILE_ATTRIBUTE_DIRECTORY ) {

// 如果是目录, 则进入该目录并递归调用函数Search_Dirctory进行查找,// 注意: 如果目录名的首字符为'.'(即为\".\"或\"..\"), 则不用进行查找

if( http://www..com/doc/9c14237945.html,[0] != '.' ) {

_chdir(http://www..com/doc/9c14237945.html,);

Search_Directory(szFilename); // 查找完毕之后, 返回上一级目录 _chdir(\"..\"); } }

else // 如果第一个实体不是目录, 则检查是否是要查找的文件 {

// stricmp对两字符串进行小写形式的对比, 返回为0表示完全一致

if( szFilename) )

{

// 先获得当前工作目录的全路径 _getcwd(path_search,_MAX_PATH);

// 再获得文件的完整的路径名(包含文件的名称) strcat(path_search,\"\\\\\");

strcat(path_search,http://www..com/doc/9c14237945.html,); MessageBox(path_search); //输出显示 } }

// 继续对当前目录中的下一个子目录或文件进行与上面同样的查找

while(!(_findnext(handle,&filestruct))) {

if( ::GetFileAttributes(http://www..com/doc/9c14237945.html,) & FILE_ATTRIBUTE_DIRECTORY ) {

if(*http://www..com/doc/9c14237945.html, != '.') {

_chdir(http://www..com/doc/9c14237945.html,); Search_Directory(szFilename);

!stricmp(http://www..com/doc/9c14237945.html,,

_chdir(\"..\"); } } {

if(!stricmp(http://www..com/doc/9c14237945.html,,szFilename))

{

_getcwd(path_search,_MAX_PATH); strcat(path_search,\"\\\\\");

strcat(path_search,http://www..com/doc/9c14237945.html,); MessageBox(path_search); } } }

_findclose(handle); // 最后结束整个查找工作 }

这样我们就可以对整个目录进行遍历搜索,查找某一特定的文件,并输出显示其完整的文件路径。以上的程序在Visual C++ 6.0中已调试通过。

. Richedit control的设置背景图片办法

1:继承CRichEditCtrl::OnEraseBkgnd(CDC* pDC)消息事件中,给

Richedit

m_bmpBackground.DrawDIB(pDC, 0, 0, rc.Width(), rc.Height());当然也可以通过subclass richedit window之后,在回调函数中处理WM_ERASEBKGND消息。

2:设置了Richedit控件的透明属性;

3:依照kenwhale所说的,Hook了GDI32.DLL中的ExtTextOut函数,将RichEdit的text-output options 去除ETO_OPAQUE style

。综上所述,即可实现RichEdit控件的背景图片效果。

据此,我还实现了RichEdit控件背景绘制A VI动画效果。 65. MFC程序中如何创建多级目录 BOOL mkdirEx(const char* lpPath) {

CString pathname = lpPath; if(pathname.Right(1) != \"\\\") pathname += \"\\\" ;

int end = pathname.ReverseFind('\\'); int pt = pathname.Find('\\'); if (pathname[pt-1] == ':') pt = pathname.Find('\\', pt+1); CString path;

while(pt != -1 && pt<=end) {

path = pathname.Left(pt+1); if(_access(path, 0) == -1) pt = pathname.Find('\\', pt+1); }

return true; }

66. 解决外部符号错误:_main,_WinMain@16,__beginthreadex 在创建MFC项目时, 不使用MFC AppWizard向导, 如果没有设置好项目参数, 就会在编译时产生很多连接错误, 如error LNK2001错误, 典型的错误提示有:

libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main

LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16

msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16

nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex

nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex

下面介绍解决的方法:

1). Windows子系统设置错误, 提示:

libcmtd.lib(crt0.obj) : error LNK2001: unresolved external symbol _main

Windows项目要使用Windows子系统, 而不是Console, 可以这样设置:

[Project] --> [Settings] --> 选择\"Link\"属性页, 在

Project Options

中将/subsystem:console

改成

/subsystem:windows

2). Console子系统设置错误, 提示:

LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16

控制台项目要使用Console子系统, 而不是Windows, 设置: [Project] --> [Settings] --> 选择\"Link\"属性页, 在

Project Options

中将/subsystem:windows

改成

/subsystem:console

3). 程序入口设置错误, 提示:

msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16

通常, MFC项目的程序入口函数是WinMain, 如果编译项目的Unicode版本, 程序入口必须改为wWinMainCRTStartup, 所以需要重新设置程序入口:

[Project] --> [Settings] --> 选择\"C/C++\"属性页, 在Category中选择Output,

再在Entry-point symbol中填入wWinMainCRTStartup, 即可 4). 线程运行时库设置错误, 提示:

nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex

nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex

这是因为MFC要使用多线程时库, 需要更改设置: [Project] --> [Settings] --> 选择\"C/C++\"属性页, 在Category中选择Code Generation,

再在Use run-time library中选择Debug Multithreaded或者multithreaded

其中,

Single-Threaded单线程静态链接库(release版本) Multithreaded多线程静态链接库(release版本) multithreaded DLL多线程动态链接库(release版本) Debug Single-Threaded单线程静态链接库(debug版本) Debug Multithreaded多线程静态链接库(debug版本) Debug Multithreaded DLL多线程动态链接库(debug版本) 单线程: 不需要多线程调用时, 多用在DOS环境下 多线程: 可以并发运行

静态库: 直接将库与程序Link, 可以脱离MFC库运行 动态库: 需要相应的DLL动态库, 程序才能运行 release版本: 正式发布时使用 debug版本: 调试阶段使用 67. 创建包含多个子目录的目录

void CreateAllDirectories(CString strDir) {

//remove ending / if exists if(strDir.Right(1)==\"\\\\\")

strDir=strDir.Left(strDir.GetLength()-1); // base case . . .if directory exists if(GetFileAttributes(strDir)!=-1)

return;

// recursive call, one less directory int nFound = strDir.ReverseFind('\\\\'); CreateAllDirectories(strDir.Left(nFound)); // actual work

CreateDirectory(strDir,NULL); }

68. ReverseFind() #include #include int main() {

CString s;

s.Format(\"abcdefghijk\"); int nPos = s.ReverseFind('a'); printf(\"nPos is %d\\n\return 0; }

其中,'a'对应的nPos是0,'h'对应的nPos是7,以此类推。但是:s.ReverseFind('a')和s.Find('a')的结果是一样的。

问题是:ReverseFind() 和Find() 有什么区别呢:

对于ReverseFind(),查找顺序是从后往前,找到后的nPos是按前后顺序排列的。

而Find()是从前往后查的,找到后的nPos也是按前后顺序排列的。 69. MDI中如何只屏蔽掉子框架的右上角的关闭按钮

int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {

if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1) return -1; 。。。

CMenu* pSysMenu = GetSystemMenu(FALSE);

pSysMenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND |MF_DISABLED|MF_GRAYED);

return 0; }

70. 程序如何删除自己

/////////////////////////////////////////////////

int WINAPI WinMain(HINSTANCE h, HINSTANCE b, LPSTR psz, int n) {

// Is this the Original EXE or the clone EXE?

// If the command-line 1 argument, this is the Original EXE // If the command-line >1 argument, this is the clone EXE if (__argc == 1) {

// Original EXE: Spawn clone EXE to delete this EXE

// Copy this EXEcutable image into the user''s temp directory TCHAR szPathOrig[_MAX_PATH], szPathClone[_MAX_PATH]; GetModuleFileName(NULL, szPathOrig, _MAX_PATH); GetTempPath(_MAX_PATH, szPathClone); GetTempFileName(szPathClone, szPathClone);

CopyFile(szPathOrig, szPathClone, FALSE); //***注意了***:

// Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL, OPEN_EXISTI

NG, FILE_FLAG_DELETE_ON_CLOSE, NULL);

// Spawn the clone EXE passing it our EXE''s process handle // and the full path name to the Original EXE file. TCHAR szCmdLine[512];

HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE,

__TEXT(\"Del\"),

0,

GetCurrentProcessId());

wsprintf(szCmdLine, __TEXT(\"%s %d \\\"%s\\\"\"), szPathClone, hProcessOrig, szPat

hOrig);

STARTUPINFO si;

ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 517ttc.cn 版权所有 赣ICP备2024042791号-8

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务