• 第一个控制台程序


    第一次使用c语言进行Windows编程的实验,可以说收获是很大的,主要是通过看线上教程(网址http://winprog.org/tutorial/zh/start_cn.html)逐步学习实现了第一个控制台程序项目。使用c语言进行windows编程,我自己的第一感觉就是相比于之前的编程,这次我调用了<windows.h>的很多库函数,代码实现基本上比较轻松,毕竟程序的底层细节都不要我自己费心去实现。代码实现给出如下,主要的细节解释已经使用注释给出。

    #include <windows.h>

    const char g_szClassName[] = "myWindowClass";
    /*
    窗口过程在每个消息到来时被调用一次,HWND参数是消息相应的窗口的句柄.这很重要因为你可能用相同
    的类创建了两个或多个窗口并且它们用相同的窗口过程(WndProc()).不同点就在不同的窗口有不同的hwnd
    参数.比如我们得到WM_CLOSE消息我们就要销毀那个窗口.我们使用了窗口句柄作为我们得到的第一个参数
    它的窗口都不会受影响,除了那个我们想要操作的之外.
    WM_CLOSE是在我们按下关闭按钮或按下Alt+F4组合时产生的.这默认会使窗口销毀,但我喜欢显式处理它,
    因为这是在程序退出之前做清除检查,或询问用戶是否保存文件等事情的绝佳的位置.
    当我们调用DestoryWindow()系统向要销毀的窗口送出WM_DESTORY消息,这里是我们的窗口,并在从系统移除
    我们的窗口之前删除它剩下的所有的子窗口.因为这是我们的程序中唯一的窗口,我们準备好了并希望
    程序退出,所以我们调用了PostQuitMessage().这样会向消息循环发出WM_QUIT消息.我们不永远收不到这个
    消息,因为它使GetMessage()返回FALSE,而且你也可以看到我们的消息循环代码中,这时候我们停止处理消
    息并返回最终的结果码,我们传递给PostQuitMessage()的WM_QUIT中的wParam部分.这个返回值只有在你的编程
    为被別的程序调用并且你需要一个确定的返回值时候才有真正有用.
    */
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    switch(msg)
    {
    case WM_LBUTTONDOWN:
    {
    printf("you have clicked left_button once! ");
    //answer:
    MessageBox(hwnd, TEXT("你点击了左键一下!"), TEXT("通知"), MB_OK | MB_ICONINFORMATION);

    char szFileName[MAX_PATH];
    //GetModuleHandle()的说明指出传给它一个NULL会返回一个创建发出调用进程的文件句柄
    HINSTANCE hInstance = GetModuleHandle(NULL);
    //消息处理函数
    GetModuleFileName(hInstance, szFileName, MAX_PATH);
    MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION);
    }
    break;

    case WM_RBUTTONDOWN:
    {
    printf("you have clicked right_button once! ");
    //answer:
    MessageBox(hwnd, TEXT("你点击了右键一下!"), TEXT("通知"), MB_OK | MB_ICONINFORMATION);

    char szFileName[MAX_PATH];
    //GetModuleHandle()的说明指出传给它一个NULL会返回一个创建发出调用进程的文件句柄
    HINSTANCE hInstance = GetModuleHandle(NULL);
    //消息处理函数
    GetModuleFileName(hInstance, szFileName, MAX_PATH);
    MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION);
    }
    break;

    case WM_MBUTTONDOWN:
    {
    printf("you have clicked middle_button once! ");
    //answer:
    MessageBox(hwnd, TEXT("你点击了中键一下!"), TEXT("通知"), MB_OK | MB_ICONINFORMATION);

    char szFileName[MAX_PATH];
    //GetModuleHandle()的说明指出传给它一个NULL会返回一个创建发出调用进程的文件句柄
    HINSTANCE hInstance = GetModuleHandle(NULL);
    //消息处理函数
    GetModuleFileName(hInstance, szFileName, MAX_PATH);
    MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION);
    }
    break;

    case WM_CLOSE:
    {
    DestroyWindow(hwnd);
    printf("windows closed! ");
    }
    break;
    case WM_DESTROY:
    {
    PostQuitMessage(0);
    printf("windows destroied! ");
    }
    break;
    default:
    return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
    }

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
    /*
    WinMain()是Windows中与DOS或UNIX的main()的等价物.这是程序开始执行的入口.参数如下:
    1.HINSTANCE hInstance
      程序可执行模块的句柄(內存中的.exe文件);
    2.HINSTANCE hPrevInstance
      在Win32程序中总是为NULL;
    3.LPSTR lpCmdLine
      命令行参数组成的一个单字符串.不包括程序名字;
    4.int nCmdShow
      一个将要传递给ShowWindow()的整数;
    */
    {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;
    /*
    结构体的成员对窗口类的影响如下:
    cbSize
      结构体的大小.
    style
      类的式样(CS_*),不要跟窗口式样(WS_*)混淆了.这个一般设置为0.
    lpfnWndProc
      指向这个窗口类的窗口过程的指针.
    cbClsExtra
      配置给这个类的额外內存.一般为0.
    cbWndExtra
      配置给这个类的每个窗口的额外內存.一般为0.
    hInstance
      应用程序实例的句柄.(从WinMain()第一个参数传递来.)
    hIcon
      当用戶按下Alt+Tab组合时候显示的大图标(一般为32*32).
    hCursor
      在我们的窗口上显示的光标.
    hbrBackground
      设置我们窗口背景顏色的背景刷子.
    lpszMenuName
      这个类的窗口所用的菜单资源的名字.
    lpszClassName
      类的名字.
    hIconSm
      在任务栏和窗口的左上角显示的小图标(一般为16*16)
    */
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;//LP前缀代表Long Pointer
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
    MessageBox(NULL, "Window Registration Failed!", "Error!",
    MB_ICONEXCLAMATION | MB_OK);
    return 0;
    }
    /*
    1.第一个参数(WS_EX_CLIENTEDGE)是扩展的窗口式样;
    2.接下来我设置了类的名字(g_szClassName),告诉系统我们要创建什么样的窗口;
    3.我们设置的WS_OVERLAPPEDWINDOW是一个窗口式样参数;
    4.接下来的四个参数(CW_USEDEFAULT,CW_USEDEFAULT,320,240)是我们窗口的左上角的X,Y坐标和其宽度
    和高度.我把X,Y坐标设为CW_USEDEFAULT来让系统自己选择在屏幕的哪个地方来放置窗口.记住屏幕的最
    左边的X坐标为0并向右加;屏幕的顶部的Y坐标为0并向底加.单位是像素,这是屏幕在特定的分辨率下能
    显示的最小单位.
    5.再接下来的四个(NULL,NULL,g_hInst,NULL)分別是父窗口的句柄,菜单句柄,应用程序实例句柄,和
    窗口创建数据的指针.在windows系统中,你屏幕上的窗口是以分层次的父窗口,子窗口的形式来组织的.
    当你看到一个窗口中有一个按钮时候,按钮就是子窗口,包含它的窗口就是父窗口.我们的例子中,父窗
    口的句柄为NULL,因为这里沒有父窗口,这个是是我们的主窗口或是顶层窗口.菜单也是NULL,因为我们现在
    也沒有菜单.实例句柄设为我们从WinMain()得到的第一个参数.窗口的创建数据(我们几乎沒有使用)可以
    用来向创建的窗口发送额外数据在这里也设为NULL.
    */
    hwnd = CreateWindowEx(
    WS_EX_CLIENTEDGE,
    g_szClassName,
    "The title of my window",
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
    NULL, NULL, hInstance, NULL);

    if(hwnd == NULL)
    {
    MessageBox(NULL, "Window Creation Failed!", "Error!",
    MB_ICONEXCLAMATION | MB_OK);
    return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    /*
    1.GetMessage()从应用的消息队列中取一个消息.任何时候用戶移动鼠标,敲击键盘,点击窗口的菜单,
    或做別的什么事,系统会产生消息并输入到程序的消息队列中去.调用GetMessage()时请求将下一
    个可用的消息从队列中删除并返回来处理.如果队列为空,GetMessage()阻塞,这意味著一直等待直
    到得到一个消息才返回.
    2.TranslateMessage()为键盘事件做一些额外的处理,如随著WM_KEYDOWN消息产生WM_CHAR消息.最后
    DispatchMessage()将消息送到消息应该被送到的窗口.
    */
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
    }
    return Msg.wParam;
    }

    测试实例:

    TZ

    2017/2/24夜

    于HZAU

  • 相关阅读:
    基础算法(C#)
    Mac系统Docker安装Redis
    Mac系统Docker安装jenkins
    设计模式-缓存驻留模式
    设计模式列表
    vs问题---...inDebugJns.Gaea.dll”标记为系统必备组件,必须对其进行强签名。
    vs问题--------------标记为系统必备组建
    Excel--------Excel实现数据对比
    IIS--------问题解决(.net开发中localhost可以访问,本地ip不可以)
    .NET--------枚举扩展方法(枚举转list,获取枚举描述)
  • 原文地址:https://www.cnblogs.com/acm-icpcer/p/6440597.html
Copyright © 2020-2023  润新知