Windows プログラミング-001


  • Win32 コンソール プロジェクト (エントリ関数がメイン関数)を作成する場合、 WinMain関数がエントリ関数として使用できないため、この問題を解決するには、プロジェクトのプロパティ -> リンカー -> システム ->サブシステムとサブシステムの変更 システムの対応する「コンソール」が「ウィンドウ」に変更されます。

  • 名詞の定義:

  • API : アプリケーション プログラミング インターフェイス (Application Programma Interface) は、一連の定義、手順、プロトコルであり、事前に定義されたインターフェイス (関数、HTTP インターフェイスなど)、またはソフトウェア システムのさまざまなコンポーネントを接続するための取り決めを指します。

  • SDK : ソフトウェア開発キット (ソフトウェア開発キット). SDK は、ソフトウェア エンジニアが特定のソフトウェア パッケージ、ソフトウェア フレームワーク、ハードウェア プラットフォーム、オペレーティング システムなどアプリケーション ソフトウェアを作成するために使用する開発ツールのコレクションです。特定のプログラミング言語のアプリケーション プログラミング インターフェイス API にいくつかのファイルを提供するだけですが、組み込みシステムと通信できる複雑なハードウェアが含まれる場合もあります。SDK には、基本的な参考資料に関する疑問を解消するためのサンプル コード、サポート技術ノート、またはその他のサポート ドキュメントも含まれていることがよくあります。

  • ウィンドウ: タイトル バー、メニュー バー、システム メニュー、ボトムダウン ボックス、最大化ボックス、スクロールなどが含まれます。ウィンドウは主にクライアント領域と非クライアント領域に分かれています。

  • ハンドル: オブジェクトまたはアイテムを識別するために使用される識別子です。データ型の観点から見ると、これは単なる 16 ビットの符号なし整数です。アプリケーションはほとんどの場合、Windows 関数を呼び出すことによってハンドルを取得し、他の Windows 関数はこのハンドルを使用して対応するオブジェクトを参照できます。Windows プログラミングでは多数のハンドルが使用されます。Windows プログラムでは、メモリ ブロック、ファイル、タスク、または動的にロードされるモジュールを識別するために物理アドレスは使用されません。代わりに、Windows API はこれらの項目に特定のハンドルを割り当て、そのハンドルをアプリケーションに返し、アプリケーションはそれらの項目に対して操作を実行します。

  • ウィンドウプログラムのエントリ関数:WinMainコンソールウィンドウアプリケーションのエントリ関数:main

  • WINAPI : 本質的に __stdcall (stdcall 呼び出しメソッドは Pascal 呼び出しメソッドとも呼ばれます) は一種の C/C++ 呼び出し規約であり、関数のパラメーターがスタックに右から左にプッシュされ、呼び出された関数がプッシュされることを意味します戻る前に右から左にこれらのパラメータをスタックからポップします。

WINAPI は、次のことを規定する関数呼び出し規約とみなすことができます。

  1. 関数がスタックにプッシュされる方法 - 右から左へ

  1. 関数呼び出しの後、スタックを元の状態に戻すのは誰でしょうか?

  • WINAPICALLBACKAPIENTRY : 右から左にスタックにプッシュします。基本的に __stdcall (標準呼び出しメソッド)。

WINAPIV : 右から左にスタックにプッシュします。本質的には __cdecel;

//转到定义,可以看到:
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
  • C++ 関数を呼び出すいくつかの方法:

  1. 標準呼び出し

stdcall 呼び出しメソッドの関数宣言は次のとおりです。 int __stdcall function(int a,intb);

stdcall の呼び出し方法は次のことを意味します。

  1. パラメータはスタックに右から左にプッシュされます。

  1. スタックは、呼び出された関数自体によって復元されます。

  1. 関数名の先頭にはアンダースコアが自動的に追加され、その後に @、その後にパラメータのサイズが続きます。

上記の関数をアセンブリ言語に翻訳すると、次のようになります。

最初に b をプッシュして 2 番目のパラメータをプッシュします

a をプッシュしてから最初のパラメータをプッシュします

関数呼び出し関数

コンパイル時に、この関数の名前は _function@8 に変換されます。

  1. cdecl

cdecl 呼び出し関数は、C 呼び出しメソッドとも呼ばれます。これは、C 言語のデフォルトの呼び出しメソッドです。その構文は次のとおりです。

int function(int a, int b)//修飾子なしは C 呼び出しメソッドです

int __cdecl function(int a,int b)//C 呼び出しメソッドを明示的に指定

cdecel の呼び出しメソッドによって次のことが決まります。

  1. パラメータはスタックに右から左にプッシュされます。

  1. スタックは呼び出し元によって復元されます。

  1. 関数名の先頭にはアンダースコアが自動的に追加されます。

呼び出し元がスタックを復元するため、C 呼び出しメソッドでは関数のパラメーターの数を固定しないことができます。これは C 言語の大きな特徴です。

この関数は次のように変換されます。

Push b //最初に 2 番目のパラメータをプッシュします

Push a //最初のパラメータを再度プッシュします

関数呼び出し // 関数呼び出し

add esp, 8 //スタックをクリアします (この内容はアセンブリの esp レジスタの関数セクションで説明されています)

コンパイル時に、この方法の関数は次のように変換されます: __function

  • 主な関数パラメータ:

  • HINSTANCE : アプリケーション インスタンスのハンドル タイプ。

//转到定义,看到本质为结构体指针:
DECLARE_HANDLE(HINSTANCE);
#define DECLARE_HANDLE(HINSTANCE)
struct HINSTANCE__
{
int unused;
};
typedef struct HINSTANCE__* HINSTANCE
  • hInstance : 現在のアプリケーション インスタンス ハンドル。

  • hPreInstance : 現在のプログラムの前のインスタンス ハンドル。32 ビットおよび 64 ビット マシンでは廃止され、使用されなくなりました。値は NULL で、16 ビット マシンで使用されます (GDI ベースの Windows プログラムは WinMain を使用します)。 Win16 では、hPreInstance はプログラムの前のインスタンス ハンドルを指しますが、Win32 では、各プロセスには 0 から 2G までの独立した 4G アドレス空間があり、これはプライベートです。したがって、Win32 では、hPreInstance は常に NULL です)。

  • LPSTR :長いポイント文字列;

typedef CHAR *NPSTR, *LPSTR, PSTR;
//上式表示 CHAR <=> NPSTR <=> LPSTR <=> PSTR
typedef char CHAR;
//LPSTR <=> char*
//LPCSTR <=> const char*
  • lpCmdLine :[in] プログラム名を除く、アプリケーションのコマンド ラインを指定するヌル終了文字列へのポインタ。コマンド ライン全体を取得するには、GetCommandLine 関数を使用します。文字で終了する文字列。GetCommandLine 関数はコマンド全体を返すことができます。ライン)

lpCmdLine は、アプリケーションに渡されるコマンド ライン パラメータを指定する null で終了する文字列です。

  • nCmdShow : ウィンドウ表示モード (最大化、最小化、通常、通常表示);

  • MessageBox : Windows プログラミングでよく使用される API の機能は、メッセージ プロンプト ボックスをポップアップすることです。

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

最初のパラメータ:

HWND: ウィンドウ ハンドル タイプ (ウィンドウの ID として理解できます)

hWnd: 親ウィンドウハンドル。親ウィンドウがない場合はNULLを書き込みます。

HWND は本質的には構造体ポインターです

/*   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*
  • 実際の操作

1.ハローワールド!

#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.ファーストウィンドウ

  • プロセス:①デザインウィンドウ、②登録ウィンドウ、③作成ウィンドウ、④表示ウィンドウ、⑤更新ウィンドウ、⑥メッセージループ。

  • ウィンドウ処理関数:

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:提供用于处理消息的其他信息。参数值取决于消息
);
*/
  • ソースコード

#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消息机制原理

おすすめ

転載: blog.csdn.net/qq_59470001/article/details/129287892