MFC的一些技巧(六)

  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, TMessage, RestrictMinimizeMaximize)
   END_MESSAGE_MAP(TForm)
  2、在Form的单元文件中添加:
  
   void __fastcall 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. 如何遍历整个目录树查找文件
  
在应用程序的开发过程中,会遇到如何查找某一文件以确定此文件路径的问题。利用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("*", &filestruct);
  // 如果handle为-1, 表示当前目录为空, 则结束查找而返回
  if((handle == -1)) return;
  // 检查找到的第一个实体是否是一个目录(filestruct.name为其名称)
  if( ::GetFileAttributes(filestruct.name) & FILE_ATTRIBUTE_DIRECTORY )
  {
   // 如果是目录, 则进入该目录并递归调用函数Search_Dirctory进行查找,
   // 注意: 如果目录名的首字符为'.'(即为"."或".."), 则不用进行查找
   if( filestruct.name[0] != '.' )
   {
     _chdir(filestruct.name);
     Search_Directory(szFilename);
     // 查找完毕之后, 返回上一级目录
     _chdir("..");
   }
  }
  else // 如果第一个实体不是目录, 则检查是否是要查找的文件
  {
   // stricmp对两字符串进行小写形式的对比, 返回为0表示完全一致
   if( !stricmp(filestruct.name, szFilename) )
   {
     // 先获得当前工作目录的全路径
     _getcwd(path_search,_MAX_PATH);
     // 再获得文件的完整的路径名(包含文件的名称)
     strcat(path_search,"//");
     strcat(path_search,filestruct.name);
     MessageBox(path_search); //输出显示
   }
  }
  // 继续对当前目录中的下一个子目录或文件进行与上面同样的查找
  while(!(_findnext(handle,&filestruct)))
  {
   if( ::GetFileAttributes(filestruct.name) & FILE_ATTRIBUTE_DIRECTORY )
   {
     if(*filestruct.name != '.')
     {
      _chdir(filestruct.name);
      Search_Directory(szFilename);
      _chdir("..");
     }
   }
   else
   {
     if(!stricmp(filestruct.name,szFilename))
     {
      _getcwd(path_search,_MAX_PATH);
      strcat(path_search,"//");
      strcat(path_search,filestruct.name);
      MessageBox(path_search);
     }
   }
  }
  _findclose(handle);
  // 最后结束整个查找工作
}
  这样我们就可以对整个目录进行遍历搜索,查找某一特定的文件,并输出显示其完整的文件路径。以上的程序在Visual C++ 6.0中已调试通过。

64. 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控件背景绘制AVI动画效果。

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)
_mkdir(path);
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 <STDIO.H>
#include <AFX.H>
int main()
{
  CString s;
  s.Format("abcdefghijk");
  int nPos = s.ReverseFind('a');
  printf("nPos is %d/n",nPos);
  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, __TEXT("Del"), 0, 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, GetCurrentProcessId());

wsprintf(szCmdLine, __TEXT("%s %d /"%s/""), szPathClone, hProcessOrig, szPat
hOrig);
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
CloseHandle(hProcessOrig);
CloseHandle(hfile);
 
// This original process can now terminate.
} else {
// Clone EXE: When original EXE terminates, delete it
HANDLE hProcessOrig = (HANDLE) _ttoi(__targv[1]);
WaitForSingleObject(hProcessOrig, INFINITE);
CloseHandle(hProcessOrig);
DeleteFile(__targv[2]);
// Insert code here to remove the subdirectory too (if desired).
 
// The system will delete the clone EXE automatically
// because it was opened with FILE_FLAG_DELETE_ON_CLOSE
}
return(0);
}
  这一段程序思路很简单:不是不能在运行时直接删除本身吗?好,那么程序先复制(CLONE)一个自己,用复制品起动另一个进程,然后自己结束运行,则原来的EXE文件不被系统保护.这时由新进程作为杀手删除原来的EXE文件,并且继续完成程序其他的功能。

  新进程在运行结束后,复制品被自动删除。这又是值得介绍的一个把戏了,注意:

// Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE
HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL,OPEN_EXISTIN
G, FILE_FLAG_DELETE_ON_CLOSE, NULL);
  这里面的FILE_FLAG_DELETE_ON_CLOSE标志,这个标志是告诉操作系统,当和这个文件相关的所有句柄都被关闭之后(包括上面这个CREATEFILE创建的句炳),就把这个文件删除。几乎所有的临时文件在创建时,都指明了这个标志。另外要注意的是:在复制品进程对原始程序操刀之前,应该等待原进程退出.在这里用的是进程同步技术.用HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE,GetCurrentProcessId());得到原进程句柄.SYNCHRONICE标志在NT下有效,作用是使OpenProcess得到的句柄可以做为同步对象.复制品进程用WaitForSingleObject函数进行同步,然后一个DeleteFile,以及进行其它销毁证据(比如删目录)的工作,一切就完事了。
 
  程序是基于CONSOLE的,通过传入的参数确定是原始的进程还是复制品新进程,并且得到需要操作的目标文件的信息(主要是路径),复制品放在系统的TEMP目录(GetTempPath得到),你也可以随便找个你认为安全的地方(比如:WINDOWS/SYSTEM32等等)。这里面没有甚么深的技术.再看其他的一些实现删除自己的例子,比如说在进程退出前,用fwrite等方法输出一个.BAT文件,在里面写几句DEL,然后WINEXEC一下这个BAT文件即可.玩儿过DOS的虫虫大多都会。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值