C/C++拾遗(十九):MFC - 一个简单的窗口程序

C++ 专栏收录该内容
17 篇文章 0 订阅
在复习完C/C++的基础之后,今天开始学习MFC,自己使用的资料是孙鑫老师的《VC++深入精解》作为主要的学习脉络,而侯老师的《深入浅出MFC》则作为补充。今天是第一章基础,简要介绍windows编程的特点。
一、几个基本的认识
1. API与SDK
     同我们经常使用的cstdlib一样,微软为进行windows程序开发的提供了强大的函数库,我们称之为API,这些API作为应用程序的接口可以被开发人员直接调用实现操作。SDK是software development Kit的简称,是一个帮助程序猿开发软件的综合平台,包含着系统提供的API、帮助文档以及其他辅助开发工具等。因此SDK通常是包含着API作为系统开发的综合平台。
     微软为我们提供了强大的API库支持,显而易见数量与功能成正比,面对1000多种API当然不可能像背字典那样的全部背过,有效的方法是借助MSDN作为工具,在实际的使用中随着使用不断学习需要的API的使用。另一方面微软提供的API命名存在着明显的规律,一般是有意义的英文单词首字母大写后的组合,如CreateFile,CreateProcess等。勤动手查阅MSDN是学习Windows编程的好方法。
2. 窗口与消息队列
     Windows系统作为经典的一款桌面系统,大部分的应用程序都提供了窗口模式。窗口作为一种资源在内存中分配有相应的空间,而这些空间的管理则依赖于句柄实现。之前讨论过C/C++中设计的句柄类,其实是一个封装了对象指针的功能类,这里也可以类似的理解,我们通过句柄可以联系到其绑定的对象,可以对对象进行相应的操作。
     与DOS系统最大的不同在于,Windows系统采用了事件驱动机制。简单来说,就是
<2.1>系统通过窗口将应用程序呈现给用户,用户在窗口上进行操作;
<2.2>系统捕捉到操作,产生消息放入应用程序的消息队列;
<2.3>应用程序从消息队列中读取消息,然后将消息发回给系统;
<2.4>系统收到消息后调用注册时指定的回调函数(APP将msg发回给系统)处理消息,做出应对
     所有的这一切都是在WinMain函数中运行的,在编写windows程序前要增加头文件
二、一个简单的window窗口程序
     创建一个带有窗口的window程序的步骤主要有四个,孙老师形象地比喻为“造汽车”:
1. 设计图纸——定义窗口类;
2. 申请报批——注册窗口类;
3. 建造汽车——创建窗口类对象;
4. 使用汽车——显示与更新窗口;
     在完成窗口的创建之后,就是编写消息循环部分,使得我们的窗口可以随时捕捉窗口上的操作,定义相应的回调函数供系统在接收到APP返回的消息时进行处理,具体的函数说明网上很多,有兴趣的童鞋可以去查看MSDN,下面给出一个简单窗口程序的代码:

点击(此处)折叠或打开

  1. //A Simple Window
  2. #include <windows.h>
  3. #include <iostream>
  4. #include <cstdlib>
  5. #include <stdio.h>

  6. //decline call-back function
  7. LRESULT CALLBACK WinProc (
  8.     HWND hwnd, //handle to window
  9.     UINT uMsg, //message id
  10.     WPARAM wParam, //1st msg parameter
  11.     LPARAM lParam //2nd msg parameter
  12. );
  13. //WinMain
  14. int WINAPI WinMain(
  15.      HINSTANCE hInstance, //handle to current instance
  16.      HINSTANCE hPrevInstance, //handle to previous instance
  17.      LPSTR lpCmdLine, //command line
  18.      int nCmdShow //show state
  19.      )
  20. {
  21.     //design a window class
  22.     WNDCLASS wndcls; //define a struct - window class
  23.     wndcls.cbClsExtra = 0;
  24.     wndcls.cbWndExtra = 0;
  25.     wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  26.     wndcls.hCursor = LoadCursor(NULL, IDC_CROSS);
  27.     wndcls.hIcon = LoadIcon(NULL, IDI_ERROR);
  28.     wndcls.hInstance = hInstance;
  29.     wndcls.lpfnWndProc = WinProc;
  30.     wndcls.lpszClassName = L"test";
  31.     wndcls.lpszMenuName = NULL;
  32.     wndcls.style = CS_HREDRAW | CS_VREDRAW;

  33.     // 注册窗口类
  34.     RegisterClass(&wndcls);

  35.     //创建窗口
  36.     HWND hwnd;
  37.     hwnd = CreateWindowA("test", "This is a Test for Windows", WS_OVERLAPPEDWINDOW, 0, 0, 600, 400, NULL, NULL, hInstance, NULL);

  38.     //显示及刷新窗口
  39.     ShowWindow(hwnd, SW_SHOWNORMAL);
  40.     UpdateWindow(hwnd);

  41.     //定义消息结构体,开始消息循环
  42.     MSG msg;
  43.     while (GetMessage(&msg, NULL, 0, 0) )
  44.     {
  45.         TranslateMessage(&msg);
  46.         DispatchMessage(&msg);
  47.     }
  48.     
  49.     return msg.wParam;
  50. }

  51. //实现窗口回调函数
  52. LRESULT CALLBACK WinProc (
  53.                          HWND hwnd,
  54.                          UINT uMsg,
  55.                          WPARAM wParam,
  56.                          LPARAM lParam)
  57. {
  58.     switch(uMsg)
  59.     {
  60.     case WM_CHAR:
  61.         char szChar[20];
  62.         sprintf(szChar, "char code is %d", wParam);
  63.         MessageBoxA(hwnd, szChar, "char", 0);
  64.         break;
  65.     case WM_LBUTTONDOWN:
  66.         MessageBoxA(hwnd, "mouse clicked", "message", 0);
  67.         HDC hdc;
  68.         hdc = GetDC(hwnd);
  69.         TextOutA(hdc, 0, 50, "菜鸟之路", strlen("菜鸟之路"));
  70.         break;
  71.     case WM_PAINT:
  72.         HDC hDC;
  73.         PAINTSTRUCT ps;
  74.         hDC = BeginPaint(hwnd, &ps);
  75.         TextOutA(hDC, 0, 0, "测试之路", strlen("测试之路"));
  76.         EndPaint(hwnd, &ps);
  77.         break;
  78.     case WM_CLOSE:
  79.         if (IDYES==MessageBoxA(hwnd, "Really end?", "message", MB_YESNO))
  80.         {
  81.             DestroyWindow(hwnd);
  82.         }
  83.         break;
  84.     case WM_DESTROY:
  85.         PostQuitMessage(0);
  86.         break;
  87.     default:
  88.         return DefWindowProc(hwnd, uMsg, wParam, lParam);
  89.     }
  90. return 0;
  91. }
      运行测试显示如下,输入一个字符时显示其ASC2码值:

     退出时点击右侧的X即可:

  • 1
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值