关于windows程序基本元素的分析

来源:互联网 发布:淘宝店铺导航字体代码 编辑:程序博客网 时间:2024/05/04 04:23

     这几天已经慢慢开始学习windows程序设计了,学习的教材是windows程序设计第五版,作者是Charles Petzold ,这本书堪称是windows程序设计的圣经,有兴趣的同学推荐值得一看。很可惜的是,这本书的中文版已经绝版,买不到正版的中文书了,只有正版的英文版,我看的是PDF,大家上网搜索一下很容易就可以得到,当然英语比较好的同学也可以挑战一下原汁原味的英文书籍。好吧,下面进入程序正文,我使用的IDE是VS2008,代码如下:

Code:
  1. // Hello.cpp : 定义应用程序的入口点。   
  2. //   
  3.   
  4. #include "stdafx.h"   
  5. #include "Hello.h"   
  6.   
  7. #define MAX_LOADSTRING 100   
  8.   
  9. // 全局变量:   
  10. HINSTANCE hInst;                                // 当前实例,执行实体(程序自身)句柄   
  11. TCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本   
  12. TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名   
  13.   
  14. // 此代码模块中包含的函数的前向声明:   
  15. ATOM                MyRegisterClass(HINSTANCE hInstance);   
  16. BOOL                InitInstance(HINSTANCEint);   
  17. LRESULT CALLBACK    WndProc(HWNDUINTWPARAMLPARAM);//HWND指窗口句柄   
  18. INT_PTR CALLBACK    About(HWNDUINTWPARAMLPARAM);   
  19.   
  20. //VS2008关于windows程序的入口点   
  21.   
  22. int APIENTRY _tWinMain(HINSTANCE hInstance,   
  23.                      HINSTANCE hPrevInstance,   
  24.                      LPTSTR    lpCmdLine,//用于执行程序的命令行   
  25.                      int       nCmdShow) //指出程序最初显示的方式   
  26. {   
  27.     UNREFERENCED_PARAMETER(hPrevInstance);   
  28.     UNREFERENCED_PARAMETER(lpCmdLine);   
  29.   
  30.     // TODO: 在此放置代码。   
  31.     MSG msg;   //MSG代表一种消息结构   
  32.     HACCEL hAccelTable;// HACCEL代表加速键表句柄   
  33.     int text;   
  34.     text=MessageBox (NULL, TEXT ("要进入程序吗?"), TEXT ("HelloMsg"), MB_OKCANCEL);   
  35.     if (text==IDCANCEL)   
  36.         return 0;   
  37.   
  38.   
  39.            
  40.   
  41. //MB代表消息框   
  42.            
  43.   
  44.   
  45.     // 初始化全局字符串   
  46.     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);//加载资源文件中的字符串   
  47.     LoadString(hInstance, IDC_HELLO, szWindowClass, MAX_LOADSTRING);//游标ID   
  48.     MyRegisterClass(hInstance);   
  49.   
  50.     // 执行应用程序初始化:   
  51.     if (!InitInstance (hInstance, nCmdShow))   
  52.     {   
  53.         return FALSE;   
  54.     }   
  55.   
  56.     hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_HELLO));//加载快捷键表   
  57.   
  58.        
  59.   
  60.   
  61.   
  62.   
  63. // 主消息循环:   
  64.     while (GetMessage(&msg, NULL, 0, 0))//从消息队列中取得消息   
  65.     {   
  66.         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))//翻译加速键表   
  67.         {   
  68.             TranslateMessage(&msg);//转译某些键盘消息   
  69.             DispatchMessage(&msg);//将消息发送给窗口消息处理程序   
  70.         }   
  71.     }   
  72.   
  73.     return (int) msg.wParam;   
  74. }   
  75.   
  76.   
  77.   
  78. //   
  79. //  函数: MyRegisterClass()   
  80. //   
  81. //  目的: 注册窗口类。   
  82. //   
  83. //  注释:   
  84. //   
  85. //    仅当希望   
  86. //    此代码与添加到Windows 95 中的“RegisterClassEx”   
  87. //    函数之前的Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,   
  88. //    这样应用程序就可以获得关联的   
  89. //    “格式正确的”小图标。   
  90. //   
  91. ATOM MyRegisterClass(HINSTANCE hInstance)   
  92. {   
  93.     WNDCLASSEX wcex;// WNDCLASSEX是一种窗口类别结构   
  94.   
  95.     wcex.cbSize = sizeof(WNDCLASSEX);   
  96.   
  97.     wcex.style          = CS_HREDRAW | CS_VREDRAW;//CS是指窗口类别样式   
  98.     wcex.lpfnWndProc    = WndProc;   
  99.     wcex.cbClsExtra     = 0;   
  100.     wcex.cbWndExtra     = 0;   
  101.     wcex.hInstance      = hInstance;   
  102.     wcex.hIcon      = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_HELLO));//加载图标供程序使用   
  103.     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);//加载鼠标光标供程序使用   
  104.     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);   
  105.     wcex.lpszMenuName   = MAKEINTRESOURCE(IDC_HELLO);   
  106.     wcex.lpszClassName  = szWindowClass;   
  107.     wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));   
  108.   
  109.     return RegisterClassEx(&wcex);   
  110. }   
  111.   
  112.   
  113.   
  114.   
  115.   
  116.   
  117.   
  118. //   
  119. //   函数: InitInstance(HINSTANCE, int)   
  120. //   
  121. //   目的: 保存实例句柄并创建主窗口   
  122. //   
  123. //   注释:   
  124. //   
  125. //        在此函数中,我们在全局变量中保存实例句柄并   
  126. //        创建和显示主程序窗口。   
  127. //   
  128. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)   
  129. {   
  130.    HWND hWnd;   
  131.   
  132.    hInst = hInstance; // 将实例句柄存储在全局变量中   
  133.   
  134.    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, //WS指窗口样式,CW指建立窗口   
  135.      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);//根据窗口类别新建一个窗口   
  136.   
  137.    if (!hWnd)   
  138.    {   
  139.       return FALSE;   
  140.    }   
  141.   
  142.    ShowWindow(hWnd, nCmdShow);//在屏幕上显示窗口   
  143.    UpdateWindow(hWnd);//指示窗口自我更新   
  144.   
  145.    return TRUE;   
  146. }   
  147.   
  148. //   
  149. //  函数: WndProc(HWND, UINT, WPARAM, LPARAM)   
  150. //   
  151. //  目的: 处理主窗口的消息。   
  152. //   
  153. //  WM_COMMAND  - 处理应用程序菜单   
  154. //  WM_PAINT         - 绘制主窗口   
  155. //  WM_DESTROY  - 发送退出消息并返回   
  156. //   
  157. //   
  158. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)   
  159. {   
  160.     int wmId, wmEvent;   
  161.     PAINTSTRUCT ps;//绘图结构   
  162.     HDC hdc;       //设备内容句柄   
  163.     RECT rect ;     //矩形结构   
  164.     switch (message)   
  165.     {   
  166.     case WM_COMMAND://WM指窗口消息   
  167.         wmId    = LOWORD(wParam);    
  168.         wmEvent = HIWORD(wParam);   
  169. //wparam是32位参数,loword是取该参数的低16位,hiword是取该参数的高16位   
  170.   
  171.            
  172.   
  173. // 分析菜单选择:   
  174.         switch (wmId)   
  175.         {   
  176.         case IDM_ABOUT:   
  177.             DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);    
  178. //根据对话框模板资源创建一个模态的对话框   
  179.             break;   
  180.         case IDM_EXIT:   
  181.             DestroyWindow(hWnd);//销毁窗口   
  182.             break;   
  183.         default:   
  184.             return DefWindowProc(hWnd, message, wParam, lParam);   
  185.         }   
  186.         break;   
  187.     case WM_PAINT:   
  188.         hdc = BeginPaint(hWnd, &ps);//开始绘制窗口   
  189.         // TODO: 在此添加任意绘图代码...   
  190.         GetClientRect (hWnd, &rect) ;//取得窗口显示区域的大小   
  191.   
  192.         DrawText (hdc, TEXT ("Hello, Windows XP!!!"), -1, &rect,DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;//显示字符串   
  193.         EndPaint(hWnd, &ps);//结束绘制窗口   
  194.         break;   
  195.     case WM_DESTROY:   
  196.         PostQuitMessage(0);//将在消息队列中插入一个“退出程序”信息   
  197.         break;   
  198.     default:   
  199.         return DefWindowProc(hWnd, message, wParam, lParam);   
  200. //默认的消息处理函数,处理未处理的消息   
  201.     }   
  202.     return 0;   
  203. }   
  204.   
  205. // “关于”框的消息处理程序。   
  206. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)   
  207. {   
  208.     UNREFERENCED_PARAMETER(lParam);   
  209.     switch (message)   
  210.     {   
  211.     case WM_INITDIALOG:   
  212.         return (INT_PTR)TRUE;   
  213.   
  214.     case WM_COMMAND:   
  215.         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)   
  216.         {   
  217.             EndDialog(hDlg, LOWORD(wParam));   
  218. // 清除一个模态对话框,并使系统中止对对话框的任何处理   
  219.             return (INT_PTR)TRUE;   
  220.         }   
  221.         break;   
  222.     }   
  223.     return (INT_PTR)FALSE;   
  224. }   
  225.   
  226.   

    大家可以试试VS2008这个IDE,个人觉得是一个很优秀的IDE,虽然易用性不及VC6,但是整个程序上手还是比较简单的,支持的高级特性也比VC6多了许多,并且也没有那么多的Bug,需要的同学可以联系我。

    值得注意的是在VS2008中,程序的默认入口点改为

int APIENTRY _tWinMain

(HINSTANCE hInstance,    HINSTANCEhPrevInstance, LPTSTR   lpCmdLine, int  nCmdShow)

而在VC6中,程序的入口点

int WINAPI WinMain

(HINSTANCE hInstance, HINSTANCE hPrevInstance,   PSTR szCmdLine, int iCmdShow)

主要区别是第三个参数由原先的PSTR改为了LPTSTR即长指针,据说是为了增强向前的兼容性,(有同学知道原因的欢迎来告诉我)自然WINAPI也变成了APIENTRY,显得更加直观一些,直译过来就是API入口。WINMAIN也变成了_tWinMain......

另外还要详细说明的一点就是关于句柄的问题,初学者往往不能很好的理解句柄的含义,这里详细的讲解一下:

 

在Windows环境中,句柄是用来标识项目的,这些项目包括:

 

*.模块(module) *.任务(task) *.实例(instance) *.文件(file) *.内存块(block of memory) *.菜单(menu) *.控制(control) *.字体(font)
*.资源(resource),包括图标(icon),光标(cursor),字符串(string)等
 

*.GDI对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),区域(region),以及设备描述表(device context)。

         WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的。相反,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。
        通俗一些来讲,句柄可以看做是C++语言中广泛提及的指针,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。

 

原创粉丝点击