<dl id="wqg5j"></dl>

    1. <menuitem id="wqg5j"></menuitem>

      <dl id="wqg5j"><font id="wqg5j"></font></dl>
    2. <dl id="wqg5j"><ins id="wqg5j"></ins></dl>
    3. <dl id="wqg5j"><ins id="wqg5j"><thead id="wqg5j"></thead></ins></dl>
      <li id="wqg5j"><ins id="wqg5j"></ins></li>
      安基网 首页 编程 C/C++ 查看内容

      一个控制台程序¡¢Windows API程序¡¢MFC程序的生命历程及差别

      2019-3-21 10:52| 投稿: xiaotiger |来自: 互联网


      免责声明£º本站系公益性非盈利IT技术普及网£¬本文由投稿者转载自互联网的公开文章£¬文末均已注明出处£¬其内容和?#35745;?#29256;权归原网站或作者所有£¬文中所述不代表本站观点£¬若有无意侵权或转载不当之处请从网站右下角联系我们处理£¬谢谢合作£¡

      摘要: 理解一个程序的生命历程能更好地理解一个程序的本质特征£¬控制台程序¡¢Windows API程序以及MFC程序的生命历程的实现有很大差别¡£DOS£¨单任务系统£©程序£¨控制台程序£©是面向批命令或事务的过程驱动程序£¬Window£¨多任务系统£©程序是面向用户的基于消息的事件驱动程序£¨Message Based£¬Event Driven£©¡£ ...

      理解一个程序的生命历程能更好地理解一个程序的本质特征£¬控制台程序¡¢Windows API程序以及MFC程序的生命历程的实现有很大差别¡£

      DOS£¨单任务系统£©程序£¨控制台程序£©是面向批命令或事务的过程驱动程序£¬Window£¨多任务系统£©程序是面向用户的基于消息的事件驱动程序£¨Message Based£¬Event Driven£©¡£Windows应用程序设计的核心就是消息的传递和处理¡£

      事件驱动程序£¨如Windows API¡¢MFC程序£©以窗口为中心£¬根据用户的不同操作激活处理相应事件的代码并完成相应的任务¡£事件驱动编程方式是一种全新的程序设计方法£¬它不是由事件的顺序来控制的£¬而是由事件的发生来控制£¬而这?#36136;?#20214;的发生是随机的¡¢不确定的£¬并没有预定的顺序£¬这样就允许程序的用户用各种合理的顺序来安排程序的流程¡£

      对于需要用户交互的应用程序来说£¬事件驱动的程序设计有着过程驱动方法无法替代的优点¡£它是一种面向用户的程序设计方法£¬它在程序设计过程中除了完成所需功能之外£¬更多地考虑了用户可能的各?#36136;?#20837;£¬并针对性地设计相应的处理程序¡£它是一种¡°被动¡±式的程序设计方法£¬程序开始运行时£¬处于等待用户输入事件状态£¬然后取得事件并做相应的?#20174;¦£?#22788;理完毕又返回并处于等待事件状态¡£

      一¡¢控制台程序的生命历程

      1 main函数执行之前£¬主要就是初始化系统相关资源

      1.1 设置栈指针£»

      1.2 初始化static静态和global全局变量£¬即data段的内容£»

      1.3 将未初始化部分的全局变量赋初值£º数值型short£¬int£¬long?#20219;?£¬bool为FALSE£¬指针为NULL£¬等等£¬即.bss段的内容

      1.4 运行全局构造器£¨如果是C++控制台程序£©£»

      1.5 将main函数的?#38382;ý£¬argc£¬argv等传递给main函数£¬然后才真正运行main函数¡£

      2 顺序执行main()函数中的代码£¬包括调用其他函数¡£

      3 程序的结束

      3.1 遇到程序终止函数£¬如abort()¡¢exit()函数£¬即结束£¨中止£©程序£»

      3.2 main()函数中的return代码行£»

      3.3 可以用atexit()或onexit 注册一个函数£¬它会在main 之后执行¡£

      二¡¢Windows API程序的生命历程

      1 程序初始化过程中调用CreateWindow£¬为程序建立了一个窗口£¬做为程序的舞台¡£CreateWindow 产生窗口之后会?#32479;öWM_CREATE 直接给窗口函数£¬后者于是可以在此时机做些初始化动作£¨例如配置内存¡¢开文件¡¢读初始资料... £©¡£

      2 程序活着的过程中£¬不断以GetMessage 从消息队列中抓取消息¡£如果这个消息是WM_QUIT£¬GetMessage 会传回0 而结束while 循环£¬进而结束整个程序¡£

      3 DispatchMessage 透过Windows USER 模块的协助与监督£¬把消息分派至窗口函数¡£消息将在该处被判别并处理¡£

      4 程序不断进行2 和3 的动作¡£

      5 当使用者按下系统菜单中的Close 命令项£¬系统?#32479;öWM_CLOSE¡£通常程序的窗口函数不栏截此消息£¬于是DefWindowProc 处理它¡£

      6 DefWindowProc 收到WM_CLOSE 后£¬ 调用DestroyWindow 把窗口清除¡£DestroyWindow 本身又会?#32479;öWM_DESTROY¡£

      7 程序对WM_DESTROY 的标准?#20174;?#26159;调用PostQuitMessage¡£

      8 PostQuitMessage 没什么其它动作£¬就只?#32479;öWM_QUIT 消息£¬准备让消息循环中的GetMessage 取得£¬如步骤2£¬结束消息循环¡£

      一个完整的windows API程序的代码请见后附¡£

      三¡¢MFC程序的生命历程

      MFC 应用程序代码一开始是一个衍生自CWinApp 的全域对象application object£¬然后是一个隐藏的WinMain 函数£¬调用application object 的InitInstance 函数£¬将程序初始化¡£初始化动作包括构造一个窗口对象£¨CFrameWnd 物件£©£¬而其构造式又调用CFrameWnd::Create 产生真正的窗口£¨并在产生之前要求MFC注册窗口类别£©¡£窗口产生后WinMain 又调用Run 激活消息循环£¬将WM_COMMAND£¨IDM_ABOUT£©和WM_PAINT 分别交给成员函数OnAbout 和OnPaint 处理¡£

      1 程序的诞生

      1.1 Application object 产生£¬内存于是获得配置£¬初值亦设立了¡£

      1.2 Afx WinMain 执行AfxWinInit£¬后者又调用AfxInitThread£¬把消息队列尽?#32771;?#22823;到96¡£

      1.3 Afx WinMain 执行InitApplication¡£这是CWinApp 的虚拟函数£¬但我们通常不改写它¡£

      1.4 AfxWinMain 执行InitInstance¡£这是CWinApp 的虚拟函数£¬我们必须改写它¡£

      1.5 CMyWinApp::InitInstance new 了一个CMyFrameWnd 对象¡£

      1.6 CMyFrameWnd 构造式调用Create£¬产生主窗口¡£我们在Create ?#38382;?#20013;指定的窗口类别是NULL£¬ 于是MFC 根据窗口种类£¬ 自行地为我们注册一个名为"AfxFrameOrView42d" 的窗口类别¡£

      1.7 回到InitInstance 中继续执行ShowWindow£¬?#20801;?#31383;口¡£

      1.8 执行UpdateWindow£¬于是发出WM_PAINT¡£

      1.9 回到AfxWinMain£¬执行Run£¬进入消息循环¡£

      2 程序开始运作

      2.1 程序获得WM_PAINT 消息£¨藉由CWinApp::Run 中的::GetMessage 循环£©¡£

      2.2 WM_PAINT 经由::DispatchMessage 送到窗口函数CWnd::DefWindowProc 中¡£

      2.3 CWnd::DefWindowProc 将消息绕行£¨routing£©过消息?#25104;?#34920;格£¨Message Map£©¡£

      2.4 绕行过程中发现有吻合项目£¬于是调用项目中对应的函数¡£此函数是应用程序利用BEGIN_MESSAGE_MAP 和END_MESSAGE_MAP 之间的宏设立起来的¡£

      2.5 标准消息的处理例程亦有标准命名£¬例如WM_PAINT 必然由OnPaint 处理¡£

      3 程序的死亡

      3.1 使用者选按¡¾File/Close¡¿£¬于是发出WM_CLOSE¡£

      3.2 CMyFrameWnd 并没有设置WM_CLOSE 处理例程£¬于是交给预设之处理例程¡£

      3.3 预设函数对于WM_CLOSE 的处理方式是调用::DestroyWindow£¬ 并因而发出WM_DESTROY¡£

      3.4 预设之WM_DESTROY 处理方式是调用::PostQuitMessage£¬因此发出WM_QUIT¡£

      3.5 CWinApp::Run 收到WM_QUIT 后会结束其内部之消息循环£¬ 然后调用ExitInstance£¬这是CWinApp 的一个虚拟函数¡£

      3.6 如果CMyWinApp 改写了ExitInstance £¬ 那么CWinApp::Run 所调用的就是CMyWinApp::ExitInstance£¬否则就是WinApp::ExitInstance¡£

      3.7 最后回到AfxWinMain£¬执行AfxWinTerm£¬结束程序¡£

      附£º

      #include 
      #include 
      #pragma comment(lib,"winmm.lib")
      //Windows项目要使用Windows子系统, 而不是Console, 可以这样设置: 
      //[Project] --> [Settings] --> 选择"Link"属性页,
      //在Project Options中将/subsystem:console改成/subsystem:windows
       
      LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
       
      int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
      {
       static TCHAR szAppName[] = TEXT("HelloWin32");
       HWND hwnd;
       MSG msg;
       WNDCLASS wndclass;
       
       wndclass.style = CS_HREDRAW | CS_VREDRAW;
       wndclass.lpfnWndProc = WndProc;
       wndclass.cbClsExtra = 0;
       wndclass.cbWndExtra = 0;
       wndclass.hInstance = hInstance;
       wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
       wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
       wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
       wndclass.lpszMenuName = NULL;
       wndclass.lpszClassName = szAppName;
       
       if (!RegisterClass(&wndclass))
       {
       MessageBox(NULL, TEXT("This program requires windows NT!"), szAppName, MB_ICONERROR);
       return 0;
       }
       
       hwnd = CreateWindow(szAppName, // window class name
       TEXT("The Hello Program"), // window caption
       WS_OVERLAPPEDWINDOW, // window style
       CW_USEDEFAULT, // initial x position
       CW_USEDEFAULT, // initial y position
       CW_USEDEFAULT, // initial x size
       CW_USEDEFAULT, // initial y size
       NULL, // parent window handle
       NULL, // window menu handle
       hInstance, // program instance handle
       NULL); // creation parameters
       
       ShowWindow(hwnd, iCmdShow);
       UpdateWindow(hwnd);
       
       while (GetMessage(&msg, NULL, 0, 0))
       {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
       }
       
       return msg.wParam;
      }
       
      LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
      {
       HDC hdc;
       PAINTSTRUCT ps;
       RECT rect;
       
       switch (message)
       {
       case WM_CREATE:
       PlaySound(TEXT("hellowin32.wav"), NULL, SND_FILENAME | SND_ASYNC);
       return 0;
       
       case WM_PAINT:
       hdc = BeginPaint(hwnd, &ps);
       
       GetClientRect(hwnd, &rect);
       DrawText(hdc, TEXT("Hello Windows 7!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
       
       EndPaint(hwnd, &ps);
       return 0;
       
       case WM_DESTROY:
       PostQuitMessage(0);
       return 0;
       }
       
       return DefWindowProc(hwnd, message, wParam, lParam);
      }
      

      £­End£­



      小编推荐£º欲学习电脑技术¡¢系统维护¡¢网络管理¡¢编程开发和安全攻防等高端IT技术£¬请 点击这里 注册账号£¬公开课频道价值万元IT培训教程免费学£¬让您少走弯路¡¢事半功倍£¬好工作升职?#26377;„¦?/font>

      本文出自£ºhttps://www.toutiao.com/a6670041647721480718/

      免责声明£º本站系公益性非盈利IT技术普及网£¬本文由投稿者转载自互联网的公开文章£¬文末均已注明出处£¬其内容和?#35745;?#29256;权归原网站或作者所有£¬文中所述不代表本站观点£¬若有无意侵权或转载不当之处请从网站右下角联系我们处理£¬谢谢合作£¡


      鲜花

      ?#24080;?/a>

      雷人

      路过

      鸡蛋

      相关阅读

      最新评论

       最新
      返回顶部
      Ðþ»úͼ
      <dl id="wqg5j"></dl>

        1. <menuitem id="wqg5j"></menuitem>

          <dl id="wqg5j"><font id="wqg5j"></font></dl>
        2. <dl id="wqg5j"><ins id="wqg5j"></ins></dl>
        3. <dl id="wqg5j"><ins id="wqg5j"><thead id="wqg5j"></thead></ins></dl>
          <li id="wqg5j"><ins id="wqg5j"></ins></li>
          <dl id="wqg5j"></dl>

            1. <menuitem id="wqg5j"></menuitem>

              <dl id="wqg5j"><font id="wqg5j"></font></dl>
            2. <dl id="wqg5j"><ins id="wqg5j"></ins></dl>
            3. <dl id="wqg5j"><ins id="wqg5j"><thead id="wqg5j"></thead></ins></dl>
              <li id="wqg5j"><ins id="wqg5j"></ins></li>