吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5452|回复: 21
收起左侧

[C&C++ 原创] [原创干货]Windows界面程序架构详解

  [复制链接]
低调的菜鸡 发表于 2019-12-3 15:52
本帖最后由 低调的菜鸡 于 2019-12-3 16:12 编辑
上次发了一个坦克大战,感谢版主和小伙伴们的支持,确实让人太感动了,这次就跟各位小伙伴们分享一下子Windows程序的简单架构,希望大家在此基础上共同学习,共同进步,话不多说,让我们进入今天的代码分享

引言

  • 众所周知,我们只要使用Windows的操作系统,必然离不开Windows的界面程序,无论是用什么语言(c 、c++、汇编、或是易语言),什么编译器,只要是带图形界面的PE文件,运行时必然带有Windows子系统,也就是说,遵循Windows界面程序的结构。
  • 那么,我们如果掌握了这个结构,无论是逆向还是开发,都会显得更加游刃有余。这也是我跟大家分享这个结构的原因,当然,如有任何错误,欢迎指正。

一、一些基础知识的介绍

  1. 什么是Windows SDK?

    • 微软推出的包含了开发该windows版本所需的windows函数和常数定义、API函数说明文档、相关工具和示例。
    • 总结起来,我们如果要在Windows上编程,离不开这玩意儿。
  2. 什么是句柄?

    • 句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。
  3. 什么是消息?

    • 在Windows中发生的一切都可以用消息来表示,消息用于告诉操作系统发生了什么,所有的Windows应用程序都是消息驱动的。
    • 换而言之,消息就是Windows程序运行的核心,我们对窗口的所有操作,包括点击,输入,都是会产生一个消息的,而程序就是不断处理我们产生的消息,从而实现不同的操作。
    • 有些大佬调试时候喜欢直接断消息,其实也就是用的这个原理
  4. 如何使用和查看Windows API?

    • Windows API是微软提供给我们在Windows下编程的接口,API丰富多彩,能做到的事情也很丰富。当然,如果熟悉了常见API函数的结构,对后期的逆向分析,代码注入或者HOOK也有很大的帮助。
    • 查看:百度-》API函数名-》MSDN-》翻译
    • 使用:程序中包含"Windows.h",直接调用即可。

二、Windows程序的结构

  1. 窗口对象

    • 用于在系统中标识该窗口,窗口的信息全部存放于其中,需要在系统中注册(使用RegisterClass函数)

    • 结构:

      typedef struct tagWNDCLASSA {
      UINT      style;            //窗口类的风格
      WNDPROC   lpfnWndProc;    //指向窗口过程的指针(重要)
      int       cbClsExtra;        //分派给窗口类的拓展的字节数
      int       cbWndExtra;        //分派给窗口实例的扩展的字节数
      HINSTANCE hInstance;        //实例句柄
      HICON     hIcon;            //类图标的句柄
      HCURSOR   hCursor;        //类鼠标指针的句柄
      HBRUSH    hbrBackground;    //刷新背景所用画刷的句柄
      LPCSTR    lpszMenuName;    //窗口类包含的菜单的资源
      LPCSTR    lpszClassName;    //窗口类名(重要)
      } WNDCLASSA, *PWNDCLASSA, *NPWNDCLASSA, *LPWNDCLASSA;
  2. 窗口

    • 根据窗口对象实际显示出来的窗口,需要根据窗口对象创建,创建成功后,返回一个句柄,也是该窗口的标识
    • 使用CreateWindow函数创建
  3. 消息泵

    • 对窗口获取到的各种消息进行处理

    • 常见结构

           MSG msg = { 0 };
           while (GetMessage(&msg, NULL, 0, 0))
           {
                   //翻译消息
                   TranslateMessage(&msg);
                   //分发消息
                   DispatchMessage(&msg);
           }
  4. 消息处理函数(窗口回调函数)

    • 消息泵将消息发送之后,消息处理函数开始执行,可以根据相应的消息进行处理。

    • 常见结构

      //窗口回调函数
      LRESULT CALLBACK WndProc(
           HWND hWnd,        /*实例句柄*/
           UINT nMsgCode,        /*消息类型*/
           WPARAM wParam, /*附加参数1*/
           LPARAM lParam  /*附加参数2*/
      )
      {
           switch (nMsgCode)
           {
           case WM_CLOSE:
                   PostQuitMessage(0);
                   break;
           default:
                   //Windows默认的消息处理
                   return DefWindowProc(hWnd, nMsgCode, wParam, lParam);
           }
           return 0;
      };

三、第一个窗口程序的流程

  1. 在系统中注册窗口类
  2. 编写窗口回调函数
  3. 创建窗口
  4. 显示刷新窗口
  5. 建立消息循环

四、代码实现

  • 说了这么多,直接看代码吧,注释很详细,大家慢慢看

    #include <stdio.h>
    #include <stdlib.h>
    #include <Windows.h>
    #include <tchar.h>
    
    //全局的一个实例句柄,标识最初的父窗口
    HWND g_hWnd = NULL;
    
    //窗口回调函数
    LRESULT CALLBACK WndProc(
          HWND hWnd,        /*实例句柄*/
          UINT nMsgCode,        /*消息类型*/
          WPARAM wParam, /*附加参数1*/
          LPARAM lParam  /*附加参数2*/
    )
    {
          switch (nMsgCode)
          {
          case WM_CLOSE:
                  PostQuitMessage(0);
                  break;
          default:
                  //Windows默认的消息处理
                  return DefWindowProc(hWnd, nMsgCode, wParam, lParam);
          }
          return 0;
    };
    
    int WINAPI WinMain(
          _In_ HINSTANCE hInstance,/*程序的实例句柄,保存的程序的加载地址*/
          _In_opt_ HINSTANCE hPrevInstance,/*已被废弃,不管*/
          _In_ LPSTR lpCmdLine,/*命令行参数*/
          _In_ int nShowCmd/*窗口的显示标志*/
    )
    {
          //1.在系统中注册窗口类
          //1.1 新建窗口类
          WNDCLASS wc = { 0 };
          //窗口类类名字段赋值
          wc.lpszClassName = _T("MyClass");
          //窗口类回调函数字段赋值
          wc.lpfnWndProc = WndProc;
    
          //1.2 注册窗口类
          RegisterClass(&wc);
    
          //2.创建窗口
          g_hWnd = CreateWindow(
                  wc.lpszClassName,                //窗口类的类名
                  _T("第一个窗口程序"),        //窗口名
                  WS_OVERLAPPEDWINDOW,        //窗口类型
                  100, 100,                                //窗口在屏幕上的位置x,y
                  640, 480,                                //窗口的宽和高
                  NULL,                                        //父窗口句柄
                  NULL,                                        //菜单的句柄
                  hInstance,                                //实例句柄
                  NULL                                        //附加参数
          );
          if (g_hWnd == NULL)
          {
                  MessageBox(NULL, _T("创建窗口失败!"), _T("ERROR"), MB_OK);
                  exit(0);
          }
          //3.显示刷新窗口
          ShowWindow(g_hWnd, SW_SHOW);
          UpdateWindow(g_hWnd);
          //4.建立消息循环
          MSG msg = { 0 };
          while (GetMessage(&msg, NULL, 0, 0))
          {
                  //翻译消息
                  TranslateMessage(&msg);
                  //发送消息
                  DispatchMessage(&msg);
          }
          //5.退出
          return (int)msg.wParam;
    }

五、运行平台

  • vs ,vc各个版本都行,复制粘贴即可运行,记得将项目属性中的链接属性,子系统改为windows子系统。

免费评分

参与人数 2吾爱币 +4 热心值 +1 收起 理由
奥古斯丁01 + 1 我很赞同!
苏紫方璇 + 3 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 低调的菜鸡 发表于 2019-12-3 16:22
bester 发表于 2019-12-3 16:16
那我还想了解一下消息的处理过程,比如 我点击软件的关闭按钮

首先是点击按钮以后,系统先获取到点击 ...

是这样的,你点击关闭按钮,系统获取到了WM_CLOSE消息,然后将它放入这个窗口的消息队列,在自己写的消息泵里,从消息队列里面拿出WM_CLOSE消息,开始分发,调用窗口回调函数,窗口回调函数中,使用PostQuitMessage给当前的窗口发送一个退出事件。然后窗口处理到退出事件时,自己就关了(仅限我发的段代码哈,vs生成的其实也是这个流程,你的猜想没问题)

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
bester + 1 + 1 我很赞同!

查看全部评分

bester 发表于 2019-12-3 16:05
提两个问题

//4.建立消息循环
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
    //翻译消息
    TranslateMessage(&msg);
    //发送消息
    DispatchMessage(&msg);
}
//5.退出
return (int)msg.wParam;
}

这里是我们的exe建立的消息循环,我的问题如下
1.这里是否是发送消息给系统?
2.系统处理完消息后,是否会调用回调函数,会调用图上的哪个回调函数?
Mr.[先知] 发表于 2019-12-3 16:05
 楼主| 低调的菜鸡 发表于 2019-12-3 16:07
bester 发表于 2019-12-3 16:05
提两个问题

//4.建立消息循环

对,这一块就是从消息队列里面获取消息,使用GetMessage,然后通过DispatchMessage将消息分发给消息处理函数,也就是窗口的回调函数,是上图的WndProc函数

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
bester + 1 + 1 我很赞同!

查看全部评分

bester 发表于 2019-12-3 16:16
低调的菜鸡 发表于 2019-12-3 16:07
对,这一块就是从消息队列里面获取消息,使用GetMessage,然后通过DispatchMessage将消息分发给消息处理 ...

那我还想了解一下消息的处理过程,比如 我点击软件的关闭按钮

首先是点击按钮以后,系统先获取到点击事件,然后把这个消息添加到消息队列,然后软件用getmessage获得这个点击事件,再分发给软件的消息处理函数,请问是这样一个流程吗?
wind-mill 发表于 2019-12-3 16:19
从头看到尾,学习了。
黄河大鲤鱼 发表于 2019-12-3 16:36
每一个字母我都认识,合起来就看不明白了
 楼主| 低调的菜鸡 发表于 2019-12-3 16:38
黄河大鲤鱼 发表于 2019-12-3 16:36
每一个字母我都认识,合起来就看不明白了

大佬别开玩笑
NvidiaChina 发表于 2019-12-3 16:43
非常学习了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 18:23

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表