• MFC中小笔记(二)


    6、有三个API函数可以运行可执行文件WinExec、ShellExecute和CreateProcess。  关于这三者的概述总结,有好几篇,自己选择。


    1.CreateProcess因为使用复杂,比较少用。 
    2.WinExec主要运行EXE文件。如:WinExec(’Notepad.exe Readme.txt’, SW_SHOW); 
    3.ShellExecute不仅可以运行EXE文件,也可以运行已经关联的文件。

    最后还有一个功能是打开目录并选中文件:

    我 们一般使用 ShellExecute 来打开一个文件或者目录,也可以用其来打开一个IE窗口、打印窗等等。 现在很多软件在打开文件所在目录的同时都会贴心的把该文件选中,比如FlashGet,BitComet。如何实现呢?很简单:) 使用 Explorer.exe的/select开关。

    //打开目录并选定文件 ShellExecute(NULL, _T("open"), _T("Explorer.exe"), _T(" /select,") + filePath, NULL, SW_SHOWDEFAULT); 
    其中 filePath 为文件的绝对路径。 ShellExecute的参数意义可以在MSDN上查到。

    注意:/select,最后是有一个,号的!!!

    还有一点需要注意:

    wchar_t wch[MAX_PATH];
    ::PathCombine(wch, _T("D:"), _T("./Temp"));  //然后调用
    ::ShellExecute(this->GetSafeHwnd(), _T("open"), wch, NULL, NULL, SW_SHOW);

    注1: ShellExecute函数中的目录或文件要用绝对路径,相对路径不行 ;

    注2:调试过程中(EXE路径)可以添加到  系统的环境变量中去,省掉不少麻烦;但是setup时候需要考虑清楚

    注3:其实调用PathCombine拼出来的字符串内容是类似: D:./Temp   对这样的格式类型,系统或ShellExecute是能自动识别的,也是合法路径。  
     

    7、只允许一个程序运行

    思路:在App程序初始化时,initinstance时检测,findwindow()进行查找,注意的是对于单文档或者多文档的需要注意  无标题-test 这种情况,有文档打开时会有 123.txt-test,这时需要将Window Title的style设置下。如上篇的第一条。

    BOOL CTestdanApp::IsFirstInstance(CString title)
    {
        CWnd *pWndPrev, *pWndChild;
    
        if (pWndPrev = CWnd::FindWindow(NULL,title))
        {
            
           // AfxMessageBox( _TEXT("只允许一个实例在运行!"));
            pWndChild = pWndPrev->GetLastActivePopup();
            if (pWndPrev->IsIconic())
                pWndPrev->ShowWindow(SW_RESTORE);
            pWndChild->SetForegroundWindow(); //找到并激活到前端
            
            CString sCopyData = GetCommandLine();
            
        COPYDATASTRUCT cpd;
            cpd.dwData = 0;
            cpd.cbData = sCopyData.GetLength() + 1;//多加一个长度,防止乱码
            cpd.lpData = (void*)sCopyData.GetBuffer(cpd.cbData);
            pWndChild->SendMessage(WM_COPYDATA,NULL,(LPARAM)&cpd);
            return FALSE;
        }
        else
            return TRUE; // 第一个实例
    }
    单一实例运行

    CMyApp中需要添加 到BOOL CMyApp::InitInstance()

    BOOL CTestdanApp::InitInstance()
    {
        if(!IsFirstInstance("titlename"))//前后title对应,尝试FindWindow(class ,null);但有的Class根据不同的环境会发生变化
            return false;
        AfxEnableControlContainer();
            。。。。
            。。。。
            return true;
    }    
    单一检测

    8、传递参数给正在运行的winfrom 程序

    在带参数的MFC程序 再次运行时,经过检测已经存在本程序,则需要不创建;然后将参数通过消息 WM_COPYDATA 传递过去

    BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) 函数中响应消息映射。

    BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) 
    {
        // TODO: Add your message handler code here and/or call default
    
        CString str;
        
        str=(char *)pCopyDataStruct->lpData;    
    
        return CFrameWnd::OnCopyData(pWnd, pCopyDataStruct);
    }

    9、通过ShellExecute 以及CMD模式下启动MFC单文档程序,其传递参数时, 在  BOOL CMyApp::InitInstance()  中接受参数。

      

        //标准用法
        CCommandLineInfo mycmdinfo;
        ParseCommandLine(mycmdinfo);
      //这两行就是CCommandLineInfo类的标准用法,实现了新建、打开文件、打印机等的操作,具体操作链接

      if (!ProcessShellCommand(mycmdinfo)) return FALSE;

       

    主要过程

    CCommandLineInfo::CCommandLineInfo()   构造函数->
    
    ->void CWinApp::ParseCommandLine(CCommandLineInfo& rCmdInfo) /*ParseCommandLine主要是对输入的命令行参数做一些分析 ;/对参数数组进行循环便利/*/ ->
    
    -> for (int i = 1; i < __argc; i++)   rCmdInfo.ParseParam(pszParam, bFlag, bLast); ->
    
    ->void CCommandLineInfo::ParseParam(const TCHAR* pszParam,BOOL bFlag,BOOL bLast) /* 根据 bFlag 进行选择*/ ->
    
    ->CCommandLineInfo::ParseParamFlag(...):   /*ParseParamFlag判断传过来的字符串 ,判断它的参数类型 , 并根据参数类型做不同的处理 . */ ->
    
    ->void CCommandLineInfo::ParseLast(BOOL bLast)   /*ParseLast会判断是否是是FileNew打开新文档 , 如果是打开新文档 , 并且打开的文档名不为空的话, 

    就假定用户想打开这个文档 , 把命令设置为FileOpen .
    */ -> ->返回到 void CWinApp::ParseCommandLine(CCommandLineInfo& ) -> ->主角登场 CWinApp::ProcessShellCommand(...): /*执行*/ ProcessShellCommand 分析m_nShellCommand ,并根据m_nShellCommand不同的类型值进行不同的处理 . switch (rCmdInfo.m_nShellCommand) -> ->完毕

     关于CCommandLineInfo详解 和 ProcessShellCommand(cmdInfo)函数功能详细解释,请点击这里

    /*
    When you start a new MFC project using the Application Wizard, the Application Wizard will create a local instance of CCommandLineInfo, and then call ProcessShellCommand and ParseCommandLine in the InitInstance member function. A command line follows the route described below:
    
      1、 After being created in InitInstance, the CCommandLineInfo object is passed to ParseCommandLine.
    
     2、   ParseCommandLine then calls CCommandLineInfo::ParseParam repeatedly, once for each parameter.
    
     3、 ParseParam fills the CCommandLineInfo object, which is then passed to ProcessShellCommand.
    
     4、   ProcessShellCommand handles the command-line arguments and flags.
    */
    MSDN解释

     定义自己的参数方法

    1、从CCommandLineInfo派生一个类,然后重载该类的ParseParam方法,实现参数的解析即可。转自链接

    如果需要定义自己的参数,则需要从CCommandLineInfo派生一个类,然后重载该类的ParseParam方法,实现参数的解析即可。
    
    //1.从CCommandLineInfo派生出类CMyCommandLineInfo:
    
    class CMyCommandLineInfo : public CCommandLineInfo
    {
    public:
            void ParseParam(LPCTSTR lpszParam, BOOL bFlag, BOOL bLast);
    };
    
    //2.在主程序App类中声明成员变量,用于保存命令行传入的参数:
    CString m_strUsername;    
    CString m_strPassword;   
     
    //3.重载ParseParam方法:
    
            void CMyCommandLineInfo::ParseParam(LPCTSTR lpszParam, BOOL bFlag, BOOL bLast)
            {
                    static int num = 0;    
                    CCommandLineInfo::ParseParam(lpszParam, bFlag, bLast);
                    switch(num)
                    {    
                            case 0:
                                    theApp.m_strUsername = CString(lpszParam);
                                    break;
                            case 1:
                                    theApp.m_strPassword = CString(lpszParam);
                                    break;
                    }
                    num++;
            }
    
    
    //该方法通过递归的方式解析命令行中传入的所有参数,依次保存到相应的变量中。
    
    //4.修改主程序的调用,用派生的CCommandLineInfo类替换默认的:
    
    CMyCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);
    
      /*通过这简单的几步,就可以方便的取得命令行参数了。要注意的是命令行在传递参数的顺序要同程序里定义的一致。如本例中,第1个参数是用户名,第2个参数是密码,如果顺序错了,程序自然不能得到正确的参数数据。*/
    转载,方法1

     2、同上,类似的例子。 转自 链接2

    MFC应用程序用以下几种方法接收命令行参数

    假设执行了命令:D:/Test.exe -arg1 -arg2

     

    1、::GetCommandLine();    //将获取到  "D:/Test.exe" -arg1 -arg2
    
    2、 for (int i=0;i<__argc;i++)  __argv[i];        //将依次得到 D:/Test.exe -arg1 -arg2
    
    3、AfxGetApp()->m_lpCmdLine;   //将获取到 -arg1 -arg2
    

      第2条 注解:

    //几个可以使用的全局变量
    _CRTIMP extern int __argc; /* count of cmd line args */ _CRTIMP extern char ** __argv; /* pointer to table of cmd line args */ _CRTIMP extern wchar_t ** __wargv; /* pointer to table of wide cmd line args */

    //如果是MFC项目,可以使用CWinAppm_lpCmdLine变量,注意这个m_lpCmdLine中不包含应用程序自身路径。

    个人方法:写出对命令行 cmdinfo 的分析解析函数,采用其中需要的参数。

    void CMyApp::ParseComand(CCommandLineInfo &commandinfo)
    {
         for(int i=1;i<__argc;i++)  //将程序的第一个参数 跳过,
        {
            CString m_str;
            m_str=__argv[i];
            MessageBox(NULL,m_str,_T("123"),MB_OK);
        }
        if (__argc>1)
        {    
            __argc=1; //其他参数进行操作后,只留下第一个参数,
            
        }    
      // 下一句,根据程序情况进行增删
      ParseCommandLine(mycmdinfo);
    }
        
    NEXT:
    
        CCommandLineInfo mycmdinfo;
        ParseComand(mycmdinfo);//------------
    
        if (!ProcessShellCommand(mycmdinfo))
            return FALSE;
     
      这个方法,可以解决出现文件不存在的情况。 如图。

    9、View、 MainFrame、 App 、Doc 相互调用

    对于单文档单VIEW的情况

    1)CMainFrame:
     

    CMyView   *pView=(CMyView   *)this‐>GetActiveView(); //this即当前CMainFrame,可省略 ,GetActiveView()可得到View指针。
    
    CMySDIDoc   *pDoc= pView->GetDocument();//GetActiveDocument()可得到Document指针,但需要依据 pView
    
    CMenu   *pMenu=this->GetMenu();  //GetMenu()获得菜单指针。


    2)CDoc:
        

    POSITION pos = GetFirstViewPosition();
    
    CView* pView = GetNextView(pos); //得到View指针  具体解释
    
         或者     
    
    CMainFrame   *pMain=(CmaimFrame   *)AfxGetApp()‐>m_pMainWnd;    
     
    CMyView   *pView=(CMyView   *)pMain‐>GetActiveView(); 


    3) CView:

    CMySDIDoc   *pDoc=this->GetDocument();    //一个视只能有一个文档,this 即CView,可省略 ,GetDocument()可得到CDoc指针。
    
    CMainFrame* pframe=(CMainFrame*)AfxGetMainWnd();//AfxGetMainWnd()可得到MainFrame指针
    
    或者
    
    CMainFrame* pframe=(CMainFrame*)AfxGetApp()->m_pMainWnd;


    4) CApp:

        成员变量 m_pMainWnd变量就是MainFrame的指针  
    
    或者
    
        CMainFrame   *pMainFrame   =(CMainFrame*)AfxGetMainWnd();
    
    或者
    
        CMainFrame   *pMainframe=(CMainFrame*)AfxGetApp();


    5) 在任何类中获得应用程序类    

     用MFC全局函数AfxGetApp()获得
    

    6) 获得状态栏与工具栏指针

    CStatusBar   *pStatusBar=(CStatusBar   *)AfxGetMainWnd()‐>GetDescendantWindow(AFX_IDW_STATUS_BAR);    
    CToolBar   *pToolBar=(CtoolBar   *)AfxGetMainWnd()‐>GetDescendantWindow(AFX_IDW_TOOLBAR);    
    
    //如果框架中加入工具栏和状态栏变量还可以这样      
    
    (CMainFrame   *)GetParent()‐>m_wndToolBar;    
    (CMainFrame   *)GetParent()‐>m_wndStatusBar; 

    注意:

    1、 在不同类之间进行调用时,需要声明,引用头文件夹  比如

    2、引用的同时有的需要引入多个文件,比如 CMyView *pView=(CMyView *)this‐>GetActiveView(); 时,需要引用

     #include "CMyDoc.h"
     #include "CMyview.h"

     同时注意引用的前后顺序。

     

     

  • 相关阅读:
    python图像仿射变换实战-提取手写数字图片样本
    详解增强算术赋值:“-=”操作是怎么实现的?
    Pycharm激活码,2020最新Pycharm永久激活码!
    Python爬虫视频教程百度云网盘免费分享
    尚学堂高淇Python400集全套视频教程百度云网盘分享
    Python入门教程哪个好?看看这套怎么样!
    python框架Django实战商城项目之工程搭建
    Python入门书籍电子版PDF百度云网盘免费下载
    廖雪峰老师Python教程及配套视频教程
    manjaro(arch)里的vbox 安装centos7后,centos无法联网的解决办法
  • 原文地址:https://www.cnblogs.com/Bachelor/p/3535066.html
Copyright © 2020-2023  润新知