Windows Programming-001


  • If you create a Win32 console project (the entry function is the main function), the WinMain function cannot be used as the entry function. If you want to solve this problem, you can open the project properties->Linker->System->Subsystem and change the subsystem The corresponding "Console" of the system is changed to "Window".

  • Definition of noun:

  • API : Application Programming Interface (Application Programma Interface) is a set of definitions, procedures and protocols . It is some predefined interfaces (such as functions, HTTP interface), or refers to the agreement for connecting different components of the software system.

  • SDK : Software Development Kit (Software Development Kit). SDK is a collection of development tools used by software engineers to create application software for specific software packages, software frameworks, hardware platforms, operating systems , etc. It can simply provide some files for an application programming interface API for a certain programming language, but it may also include complex hardware that can communicate with an embedded system. SDKs also often include sample code, supporting technical notes, or other supporting documentation to clarify doubts about basic reference materials.

  • Window : includes title bar, menu bar, system menu, bottom-down box, maximize box, scrolling, etc. The window is mainly divided into client area and non-client area;

  • Handle : is an identifier used to identify an object or item. From the data type point of view, it is just a 16-bit unsigned integer. Applications almost always obtain a handle by calling a Windows function, which can then be used by other Windows functions to reference the corresponding object. A large number of handles are used in Windows programming. In Windows programs, physical addresses are not used to identify a memory block, file, task, or dynamically loaded module. Instead, the Windows API assigns specific handles to these items and returns the handles to the application, which then performs operations on them.

  • Entry function of window program: WinMain Entry function of console window application: main

  • WINAPI : Essentially __stdcall, (stdcall calling method is also called Pascal calling method) is a kind of C/C++ calling convention, which means that the parameters of the function are pushed onto the stack from right to left, and the called function is pushed from right to left before returning. Pop these parameters from the stack;

WINAPI can be regarded as a function calling convention, which stipulates:

  1. How functions are pushed onto the stack - from right to left

  1. After a function call, who will restore the stack to its original state?

  • WINAPI , CALLBACK , APIENTRY : push onto the stack from right to left, essentially __stdcall (standard calling method);

WINAPIV : push onto the stack from right to left, essentially __cdecel;

//转到定义,可以看到:
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
  • Several ways to call C++ functions:

  1. stdcall

The function declaration of stdcall calling method is: int __stdcall function(int a,intb);

The way stdcall is called means:

  1. Parameters are pushed onto the stack from right to left;

  1. The stack is restored by the called function itself;

  1. The function name is automatically appended with a leading underscore, followed by an @, followed by the size of the parameter.

The above function translated into assembly language will become:

push b first pushes in the second parameter

push a and then push the first parameter

call functioncall function

At compile time, the name of this function is translated to _function@8

  1. cdecl

The cdecl calling function is also called the C calling method. It is the default calling method of the C language. Its syntax is:

int function(int a, int b)//without modifier is the C calling method

int __cdecl function(int a,int b)//Explicitly specify the C calling method

The calling method of cdecel determines:

  1. Parameters are pushed onto the stack from right to left;

  1. The stack is restored by the caller;

  1. Function names are automatically appended with leading underscores.

Since the caller restores the stack, the C calling method allows the number of parameters of the function to be unfixed, which is a major feature of the C language.

This function is translated as:

push b //Push in the second parameter first

push a //Push in the first parameter again

call function // call function

add esp, 8 //Clear the stack (this content is discussed in the function section of the esp register in the assembly)

At compile time, functions this way are translated to: __function

  • Main function parameters:

  • HINSTANCE : application instance handle type;

//转到定义,看到本质为结构体指针:
DECLARE_HANDLE(HINSTANCE);
#define DECLARE_HANDLE(HINSTANCE)
struct HINSTANCE__
{
int unused;
};
typedef struct HINSTANCE__* HINSTANCE
  • hInstance : current application instance handle;

  • hPreInstance : The previous instance handle of the current program. It is obsolete on 32- and 64-bit machines and is no longer used. The value is NULL and is used on 16-bit machines (any GDI-based Windows program uses the WinMain function as the entry point to be used by the system. Call, in Win16, hPreInstance points to the previous instance handle of the program, but in Win32, each process has an independent 4G address space, from 0 to 2G, which is private to the process and invisible to other processes. So in Win32, hPreInstance is always NULL);

  • LPSTR:long point string;

typedef CHAR *NPSTR, *LPSTR, PSTR;
//上式表示 CHAR <=> NPSTR <=> LPSTR <=> PSTR
typedef char CHAR;
//LPSTR <=> char*
//LPCSTR <=> const char*
  • lpCmdLine :[in] Pointer to a null-terminated string specifying the command line for the application, excluding the program name. To retrieve the entire command line, use the GetCommandLine function. Character-terminated string. The GetCommandLine function can return the entire command line)

lpCmdLine is a null-terminated string specifying the command line parameters passed to the application.

  • nCmdShow : Window display mode (maximize, minimize, normal, normal display);

  • MessageBox : An API often used in Windows programming. Its function is to pop up a message prompt box;

int WINAPI MessageBox (
In_opt HWND hWnd,
In_opt LPCTSTR lpText,      //要在消息框中显示的文本
In_opt LPCTSTR lpCaption,   //对话框标题。如果为 NULL(默认值),则使用标题“错误”
In UINT uType       //指定对话框的内容和行为。有关可用不同消息框的列表,请参阅 Windows SDK 文档中的消息框条目。默认值提供一个简单的“确定”按钮。
);

First parameter:

HWND: Window handle type (can be understood as the ID of the window)

hWnd: Parent window handle, if there is no parent window, write NULL

HWND is essentially a structure pointer

/*   HWND : 窗口句柄类型(可以理解为窗口的ID)
     hWnd : 父窗口句柄,如果没有父窗口,就写NULL
     HWND 本质为结构体指针                  */
DECLARE_HANDLE (HWND);
#define DECLARE_HANDLE(name) 
struct HWND__
{
  int unused;
};     
  typedef struct HWND__ *HWND
/*LPCTSTR:显示内容*/
//LPCTSTR在Unicode编码下
typedef LPCWSTR PCTSTR, LPCTSTR;          //LPCWSTR <=> PCTSTR <=> LPCTSTR
typedef  CONST WCHAR *LPCWSTR, *PCWSTR;   //CONST WCHAR* <=> LPCWSTR <=> PCWSTR
#define CONST               const         //CONST <=> const
typedef wchar_t WCHAR;                    //wchar_t <=> WCHAR
    //const wchar_t* <=>  LPCTSTR
//上述内容:LPCTSTR <=> const wchar_t*
/*LPSTR在多字节字符集情况下*/
typedef LPCTSTR PCTSTR, LPCTSTR;           //LPCTSTR  <=> PCTSTR <=> LPCTSTR
typedef  CONST CHAR *LPCWSTR, *PCWSTR;     //CONST CHAR* <=> LPCTSTR <=> PCWSTR
#define CONST const                        //CONST <=> const
typedef char CHAR;                         //char <=> CHAR
//上述内容:LPSTR <=> const char*
  • Practical operation

1.Hello World!

#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine , int nCmdShow)
{
    int n = MessageBox(NULL, L"Hello World!", L"温馨提示", MB_OK);
    if (n == IDOK)
    {
        MessageBox(NULL, L"点了OK", L"提示", MB_OK);
    }
    else if (n == IDNO)
    {
        MessageBox(NULL, L"点了No", L"提示", MB_OK);
    }
    else if (n == IDYES)
    {
        MessageBox(NULL, L"点了Yes", L"提示", MB_OK);
    }

    return 0;
}

2.FirstWindow

  • Process: ① design window; ② registration window; ③ create window; ④ display window; ⑤ update window; ⑥ message loop.

  • Window handling function:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//typedef LONG_PTR            LRESULT;

/*virtual LRESULT WindowProc(
   UINT message,        //message:指定要处理的Windows消息
   WPARAM wParam,       //wParam:提供用于处理的其他信息。参数值取决于消息
   LPARAM lParam        //lParam:提供用于处理消息的其他信息。参数值取决于消息
);
*/
  • source code

#include <Windows.h>
#include "resource.h"

//LRESULT:
//typedef LONG_PTR            LRESULT;   long

//第一个参数:窗口句柄
//当前窗口的窗口句柄

//第二个参数:消息编号   unsigned int

//第三个参数:WPARAM     unsigned int
//窗口附加信息

//第四个参数:LPARAM     long
//窗口附加信息


//窗口处理函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow)
{
    /*
    
    typedef struct tagWNDCLASSW {
    UINT        style;
    WNDPROC     lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;
    LPCWSTR     lpszMenuName;
    LPCWSTR     lpszClassName;
} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;
#ifdef UNICODE
typedef WNDCLASSW WNDCLASS;

    UINT
    
    */
    //UINT    //typedef unsigned int        UINT;

    //一、设计窗口类

    wchar_t szAppClassName[] = L"My_GUI";
    wchar_t szWindowName[] = L"这是我的第一个Windows程序";

    //LoadIcon
    //加载一个图标文件
    //第一个参数:应用程序实例句柄
    //如果是系统资源,传递NULL
    //如果是自定义资源,传递hInstance

    //第二个参数:资源ID


    //LoadCursor
    //加载一个光标文件
    //第一个参数:应用程序实例句柄
    //如果是系统资源,传递NULL
    //如果是自定义资源,传递hInstance

    //第二个参数:资源ID

    WNDCLASS wc;
    wc.style = CS_HREDRAW | CS_VREDRAW;            //窗口类的风格
    wc.lpfnWndProc = WindowProc;                //窗口处理函数
    wc.cbClsExtra = 0;                            //窗口类的额外扩展空间大小(字节)
    wc.cbWndExtra = 0;                            //窗口的额外扩展空间大小(字节)
    wc.hInstance = hInstance;                    //当前应用程序实例句柄
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LOGO));                            //窗口图标句柄,NULL:没有图标
    wc.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR));                            //光标图标句柄
    wc.hbrBackground = CreateSolidBrush(RGB(255,255,255)); //背景画刷句柄, 0-》255,0:最暗;255:表示最亮  白色:RGB(255,255,255)  红色:RGB(255,0,0)
    wc.lpszMenuName = NULL;                        //菜单名
    wc.lpszClassName = szAppClassName;            //窗口类型名

    //二、注册窗口类
    //ATOM <= > WORD  <=> unsigned short 
    //DWORD  double WORD   
    //DWORD  <=> unsigned long

    if (0 == RegisterClass(&wc))
    {
        MessageBox(NULL, L"此程序不能运行在Windows NT上", L"温馨提示", MB_OK);
        return 0;
    }

    //三、创建窗口
    HWND hWnd = CreateWindow(
        szAppClassName,                            //窗口类型名
        szWindowName,                            //窗口的标题
        WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,//窗口的风格
        200,                                    //窗口左上角横坐标
        200,                                    //窗口左上角纵坐标
        800,                                    //窗口的宽度
        600,                                    //窗口的高度
        NULL,                                    //父窗口句柄
        NULL,                                    //菜单句柄
        hInstance,                                //应用程序实力句柄
        NULL                                    //创建窗口需要传递的信息
        );

    if (hWnd == NULL)
    {
        MessageBox(NULL, L"创建窗口失败", L"温馨提示", MB_OK);
        return 0;
    }

    //四、显示窗口
    ShowWindow(hWnd, SW_SHOW);

    //五、更新窗口
    UpdateWindow(hWnd);

    //六、消息循环

    /*
    typedef struct tagMSG {
    HWND        hwnd;                        //消息发给哪一个窗口的窗口句柄
    UINT        message;                    //消息编号,
    WPARAM      wParam;                        //附加信息
    LPARAM      lParam;                        //附加信息
    DWORD       time;                        //消息投放到消息队列里面的时间
    POINT       pt;                            //消息放入消息队列的时候鼠标的坐标
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;
    */
    
    //只要收到了 WM_QUIT消息,函数返回:0
    
    
    MSG msg;

    while (GetMessage(&msg, NULL, 0, 0))
    {
        //将虚拟键消息转为字符消息
        TranslateMessage(&msg);

        //将虚拟键消息分发给窗口处理函数
        DispatchMessage(&msg);
    }


    return 0;//程序退出了,结束了
}

//窗口处理函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CLOSE://窗口关闭消息
        //MessageBox(NULL, L"点了关闭按钮", L"提示", MB_OK);
        DestroyWindow(hWnd);//销毁窗口
        break;
    case WM_DESTROY://窗口销毁消息
        PostQuitMessage(0); //发出一个退出消息 :WM_QUIT
        break;
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);//操作系统默认处理消息的函数
}

//Windows消息机制原理

Guess you like

Origin blog.csdn.net/qq_59470001/article/details/129287892