• 第一个手写Win32窗口程序


    第一个手写Win32窗口程序

    一 Windows编程基础

    1 Win32应用程序的基本类型

    1.1 控制台程序
    不需要完善的Windows窗口,可以使用DOS窗口
    的方式显示。
    1.2 Win32窗口程序
    包含窗口的程序。可以通过窗口与程序进行交互。
    1.3 Win32库程序
    提供已有的代码,供其他程序使用。
    动态库:DLL 是在执行的时候可以加载的程序。
    静态库:LIB 是在编译链接是使用的程序。
    1.4 对比
    1.4.1 程序的入口函数不同
    控制台:main
    Win32窗口程序:WinMain
    动态库DLL:DllMain
    静态库LIB:无

    1.4.2 编译链接后存在的形式不同
    控制台和Win32窗口程序:EXE文件,可以执行
    动态库DLL:DLL文件,无法执行
    静态库LIB:LIB文件,无法执行

    1.4.3 执行结果不同
    控制台:使用DOS窗口,自己没有窗口。
    Win32窗口程序:会产生自己的窗口,
    可以将结果输出或者从窗口接受输入。
    动态库DLL:自己无法执行,提供可以执行
    的代码,当EXE等程序执行时,可以使用
    这些代码.执行时,该库必须在指定的路径.
    静态库LIB: 自己无法执行,提供给程序在
    编译链接时使用,将库中的代码嵌入到
    程序当中.执行时,不需要该库存在.

    二 Win32窗口程序和编译环境

    2.1 开发和编译环境
    VC1.5 - VC6.0(2008) - VC10.0(2010)

    2.1.1 编译器 CL.EXE(在VC安装目录的VC98/Bin目录下)
    将原代码编译目标代码. OBJ文件.
    2.1.2 链接器 Link.EXE(在VC安装目录的VC98/Bin目录下)
    将OBJ文件和库函数链接.生成EXE.
    2.1.3 资源编译器 rc.exe(在VC安装目录的MSDev98Bin目录下)
    将资源脚本编译成可以链接的文件(RES).

    2.2 头文件和库
    2.2.1 头文件 windows.h包含了windows
    常用的定义等.其他,还包含了一些其他的
    头文件:
    windef.h - 定义了各种的数据类型
    winbase.h- 定义了kernel的相关函数
    wingdi.h - 定义了绘图和文字
    winuser.h- 窗口 控件等函数
    winnt.h - 提供Unicode支持

    2.2.2 库
    kernel32.lib - 提供进程/线程/内存等等
    API函数支持
    user32.lib - 包括窗户/界面等等.
    gdi32.lib - 提供绘图/文字等。

    2.3 Hello World程序

    2.3.1 入口函数
    int WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR pszCmdLine,
    int nShowCmd )
    hInstance - 应用程序的实例句柄
    hPrevInstance - 该应用程序的前一个实例句柄
    pszCmdLine - 命令行参数
    nShowCmd - 窗口的显示方式

    2.3.2 MessageBox

    2.4 编译环境的准备

    在VC98的BIN目录下VCVARS32.BAT

    2.5 编译CL.EXE
    CL的常用选项
    /c 只编译不链接
    /TC 编译C文件
    /TP 编译C++文件
    如果不指定,CL会根据文件类型自动区分
    /I 头文件所在路径
    字符大小写敏感
    2.6 链接LINK.EXE
    LINK常用选项:
    /out:文件名,链接成指定文件名的程序
    /LIBPATH:LIB文件存放的路径, /LIBPATH:"E:XXX"
    /SUBSYSTEM: CONSOLE/WINDOW
    字符大小写不敏感

    2.7 执行
    正常执行或带参数执行

    三 第一个窗口程序

    3.1 入口函数WinMain
    3.2 窗口处理函数
    当窗口处理消息事件时,系统调用该函数
    LRESULT CALLBACK WindowProc(
    HWND hwnd, // 窗口的句柄
    UINT uMsg, // 消息的ID号
    WPARAM wParam, // 消息所对应的参数
    LPARAM lParam // 消息所对应的参数
    );
    3.3 注册窗口类型
    typedef struct _WNDCLASS {
    UINT style; //窗口类的风格
    WNDPROC lpfnWndProc; //窗口处理函数
    int cbClsExtra; //窗口类附加数据大小
    int cbWndExtra; //窗口附加数据大小
    HANDLE hInstance; //当前应用程序的实例句柄
    HICON hIcon; //窗口图标
    HCURSOR hCursor; //窗口的鼠标
    HBRUSH hbrBackground; //窗口的背景画刷
    LPCTSTR lpszMenuName; //菜单
    LPCTSTR lpszClassName; //类型名称
    } WNDCLASS;

    注册函数 RegisterClass
    3.4 创建窗口
    HWND CreateWindow(
    LPCTSTR lpClassName, //窗口类型名称
    LPCTSTR lpWindowName, //窗口名称
    DWORD dwStyle, //窗口类型
    int x, //窗口的左上角X坐边
    int y, //窗口的左上角X坐边
    int nWidth, //窗口的宽度
    int nHeight, //窗口的高度
    HWND hWndParent, //父窗口句柄
    HMENU hMenu, //窗口菜单句柄
    HANDLE hInstance, //应用程序的实例句柄
    LPVOID lpParam //创建的参数,一般为NULL
    );

    3.5 显示窗口
    ShowWindow 显示窗口
    BOOL ShowWindow(
    HWND hWnd, //显示的窗口句柄
    int nCmdShow //显示的方式
    );
    UpdateWindow 刷新窗口
    3.6 消息处理
    GetMessage 获取消息
    DispatchMessage 派发消息

    3.7 程序退出
    窗口销毁时,退出程序。在WndProc中实现。
    WM_DESTROY: 当窗口销毁时,会调用WndProc
    传递给使用者。
    PostQuitMessage:发送一个退出消息。

    四 资源的处理

    4.1 资源和资源脚本
    资源:ICON/CUSRUR/BITMAP/MENU......
    资源脚本: 扩展名为rc文件。
    4.2 编译资源
    使用rc.exe编译资源,生成RES文件
    4.3 链接资源
    使用link.exe将RES文件链接到程序当中
    4.4 ICON的使用
    LoadIcon从指定程序中加载ICON资源。

    HelloWorld.c代码如下:

      1 #include <windows.h>
      2 
      3 
      4 // 2、窗口过程函数
      5 LRESULT CALLBACK WindowProc(  HWND hwnd,
      6                               UINT uMsg,
      7                               WPARAM wParam,
      8                               LPARAM lParam )
      9 {
     10     //判断消息ID
     11     switch (uMsg)
     12     {
     13         case WM_DESTROY:    // 窗口销毁消息
     14             PostQuitMessage( 0 );   //  发送退出消息
     15             return 0;
     16     }
     17     // 其他的消息调用缺省的消息处理程序
     18     return DefWindowProc( hwnd, uMsg, wParam, lParam );
     19 }
     20 
     21 // 3、注册窗口类型
     22 BOOL RegisterWindow( LPCSTR lpcWndName, HINSTANCE hInstance )
     23 {
     24     ATOM nAtom = 0;
     25 
     26     // 构造创建窗口参数
     27     WNDCLASS wndClass = { 0 };
     28     
     29     wndClass.style = CS_HREDRAW | CS_VREDRAW;
     30     wndClass.lpfnWndProc = WindowProc;      // 指向窗口过程函数
     31     wndClass.cbClsExtra = 0;
     32     wndClass.cbWndExtra = 0;
     33     wndClass.hInstance = hInstance;
     34     wndClass.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( 100 ) );// 100为在HelloWorld.rc文件中定义的ID号
     35     wndClass.hCursor = NULL;
     36     wndClass.hbrBackground = (HBRUSH)COLOR_GRAYTEXT;
     37     wndClass.lpszMenuName = NULL;
     38     wndClass.lpszClassName = lpcWndName;    // 注册的窗口名称,并非标题,以后创建窗口根据此注册的名称创建
     39     
     40     nAtom = RegisterClass( &wndClass );
     41     if( 0 == nAtom)
     42     {
     43         MessageBox( NULL, "Register Failed",
     44                     "Error", MB_OK|MB_ICONERROR );
     45         return FALSE;
     46     }
     47     else
     48     {
     49         MessageBox( NULL, "Register Successed",
     50                     "Sucessed", MB_OK );
     51     }
     52     return TRUE;
     53 }
     54 
     55 // 4、创建窗口(lpClassName 一定是已经注册过的窗口类型)
     56 HWND CreateMyWindow( LPCTSTR lpClassName, HINSTANCE hInstance )
     57 {
     58     HWND hWnd = NULL;
     59     // 创建窗口
     60     hWnd = CreateWindow( lpClassName, "Hello World",
     61                   WS_OVERLAPPEDWINDOW,
     62                   0, 0, 500, 300,
     63                   NULL, NULL, hInstance, NULL );
     64     if( NULL == hWnd )
     65     {
     66         MessageBox( NULL, "Create Window Failed",
     67                     "Error", MB_OK|MB_ICONERROR );
     68         return NULL;
     69     }
     70     else
     71     {
     72         MessageBox( NULL, "Create Window Successed",
     73                     "Sucessed", MB_OK );
     74     }
     75     return hWnd;
     76 }
     77 
     78 // 5、 显示窗口
     79 void DisplayMyWnd( HWND hWnd )
     80 {
     81     ShowWindow( hWnd, SW_SHOW );
     82     UpdateWindow( hWnd );
     83 }
     84 
     85 void doMessage()        // 消息循环处理函数
     86 {
     87     MSG msg = { 0 };
     88     // 获取消息
     89     while( GetMessage( &msg, NULL, 0, 0 ) ) // 当接收到WM_QIUT消息时,GetMessage函数返回0,结束循环
     90     {
     91         DispatchMessage( &msg ); // 派发消息,到WindowPro函数处理
     92     }
     93 }
     94 
     95 
     96 // 1、 入口函数
     97 int WINAPI WinMain( HINSTANCE hInstance,
     98                     HINSTANCE hPrevInstance,
     99                     LPWSTR lpCmdLine,
    100                     int nShowCmd )
    101 {
    102     HWND hWnd = NULL;
    103     LPCTSTR lpClassName = "MyWnd";  // 注册窗口的名称
    104     RegisterWindow( lpClassName, hInstance );
    105     hWnd = CreateMyWindow( lpClassName, hInstance );
    106 
    107     DisplayMyWnd( hWnd );
    108     doMessage();
    109     
    110     return 0;
    111 }

    HelloWorld.rc资源脚本如下:

    其中 100:表示资源的ID号

           ICON:表示资源的类型

         ”resources/ICO.ico“ 表示资源Ico图标的路径

    1 100 ICON "resources/ICO.ico"

    运行方法:(首先运行VC98/bin/VCVARS32.bat配置好运行环境)

    1、在Cmd控制台中找到代码当前路径,使用CL HelloWorld.c /c  命令只编译不链接文件,会生成一个HelloWorld.obj的目标文件

    2、使用 rc HelloWorld.rc 命令编译HelloWorld.rc 资源脚本文件,会生成一个HelloWorld.RES的编译过的资源脚本文件

    3、使用 link HelloWorld.obj user32.lib HelloWorld.res 链接这几个文件,会生成一个带图标的HelloWorld.exe文件

    4、可以在 cmd 窗口中继续使用 HelloWorld 命令运行该程序,也可以点击生成的HelloWorld.exe运行改程序

    运行结果如下:

    (1)                                                  (2)    

                                    

    (3)可以看到左上角的图标也改变了

  • 相关阅读:
    Eclipse 安装Activiti插件(BPMN打开工具)
    POI Excel 单元格内容类型判断并取值
    AJAX获取数据成功后的返回数据如何声明成全局变量
    java 思维导图
    java excel Workbook API
    金额 保留两位小数
    mybatis教程3(映射文件)
    mybatis教程1(基本使用)
    mybatis教程之原理剖析
    Maven教程4(私服-nexus)
  • 原文地址:https://www.cnblogs.com/dongsheng/p/3477808.html
Copyright © 2020-2023  润新知