zoukankan      html  css  js  c++  java
  • Win32-HINSTANCE和HWND理解

    Windows程序设计相关参数理解

    WinMain入口函数
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    
    窗口回调函数(消息处理函数)
    
    LRESULT CALLBACK WindowProc(
                                IN  HWND hwnd,
                                IN  UINT uMsg,
                                IN  WPARAM wParam,
                                IN  LPARAM lParam
                                );
    

    HINSTANCE理解

    • 1.变量类型 HINSTANCE
    • (1) HINSTANCE是Windows里面的一种数据类型,其实她本质就是个无符号长整型,针对32位的Windows操作系统,她用于标记或者说记录一个程序的实例,她与HMODULE是一样的,这两种类型最终都是无符号长整型;
    • (2) HINSTANCE,如果分开看的话,就是H+INSTANCE,其中H代表HANDLE(翻译为"句柄"),INSTANCE翻译就是"实例"的意思
    • (3) 实例HINSTANCE在VC++6.0上查找对应定义的具体代码选中HINSTANCE,且包含Windows的头文件然后F12找到对应定义的位置在C:Program FilesMicrosoft Visual StudioVC98IncludeWINDEF.H
    DECLARE_HANDLE(HINSTANCE);
    

    image

    • (4) 看到前面定义的是DECLARE_HANDLE,再次F12进去看看具体代码,得到如下位置:C:Program FilesMicrosoft Visual StudioVC98IncludeWINNT.H
    #ifdef STRICT
    typedef void *HANDLE;
    #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
    #else
    typedef PVOID HANDLE;
    #define DECLARE_HANDLE(name) typedef HANDLE name
    #endif
    typedef HANDLE *PHANDLE;
    

    image

    • (5) 通过上面的代码发现DECLARE_HANDLE()是一个条件预定义,那么根据这个条件STRICT查看是否成立,再次选中STRICT按住F12进行查看
    #ifndef _WINDEF_
    #define _WINDEF_
    
    #ifndef NO_STRICT
    #ifndef STRICT
    #define STRICT 1
    #endif
    #endif /* NO_STRICT */
    

    image

    • (6) 通过上面的STRICT的定义为1,得知其是默认被定义的,这样我们再回头看看上面的代码
    #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
    
    • (7) 上面代码其中##在宏里面是表示字符连接的作用,所以回到上面DECLARE_HANDLE(name)代码我们就可以有如下理解
    DECLARE_HANDLE(name) 根据实例WinMain实例函数,就变成了DECLARE_HANDLE(HINSTANCE)
    再开始宏扩展
    DECLARE_HANDLE(HINSTANCE)变成如下:
    
    struct HINSTANCE__ { int unused; }; typedef struct HINSTANCE__ *HINSTANCE
    
    struct HINSTANCE__
    {
    int unused;
    };
    typedef struct HINSTANCE__ *HINSTANCE
    
    得到上面的结果,然后我们可以这样理解:
    
    定义了一个结构体HINSTANCE__,这个结构体里面就只有一个int类型的变量;
    然后将这个结构体HINSTANCE__变成结构体指针类型:HINSTANCE__* ;
    最后才将HINSTANCE__*这个结构体指针类型别名为HINSTANCE;
    
    

    总结:HINSTANCE是个数据类型,本质就是个结构体指针,里面结构体成员只有一个int类型变量,指向的是PE结构中讲到的ImageBase,仅此而已;

    HWND理解

    • 2.变量类型 HWND
    • (1) HWND同样是个数据类型,可以把她看作像是身份证号一样,是唯一的标识,当窗口被创建的时候会分配一个句柄,这个句柄是唯一的,可以通过这个句柄找到窗口的各种属性;
    • (2) HWND可以拆分为H和WND,其中H是Handle,就会是句柄的一些,而WND就是变量对象的描述,全称就是Windows,合起来就是Handle of Windows,缩写就是上面我们所的HWND,翻译为窗口句柄;
    • (3) 同样的操作,包含Windows头文件,选中HWND按住F12进入定义的代码,如下:
    路径:C:Program FilesMicrosoft Visual StudioVC98IncludeWINDEF.H
    DECLARE_HANDLE            (HWND);
    

    image

    • (4) 看到上面的代码同样定义了DECLARE_HANDLE,而这跟上面HINSTANCE的定义是一样的,所以这里不就再查看重复的代码定义内容,也因为如此,可以得出同样的结论,HWND也是个结构体类型指针,里面定义的类型同样是int类型,只是她这个结构体指针指向的是Windows给其分配的一个唯一的ID而已;

    总结:HWND同样是个数据类型,只是改了名称叫法而已,叫做窗口句柄,将其实例化后,就是个整型int类型的数据,只是是用指针的方式指向她,其本质是个结构体指针,里面结构体成员只有一个int类型变量,所以HWND是个带有int类型成员的结构体指针,指向每个不同的窗口,并且给不同的窗口分配唯一的编号,通过这个编号就能找到不同的窗口,仅此而已;

    根据实例代码理解

    #include "stdafx.h"
    
    HINSTANCE hAppInstance;
    
    LRESULT CALLBACK WindowProc(
                                IN  HWND hwnd,
                                IN  UINT uMsg,
                                IN  WPARAM wParam,
                                IN  LPARAM lParam
                                );
    
    void __cdecl OutputDebugStringF(const char *format, ...)
    {
        va_list vlArgs;
        char    *strBuffer = (char*)GlobalAlloc(GPTR, 4096);
    
        va_start(vlArgs, format);
        _vsnprintf(strBuffer, 4096 - 1, format, vlArgs);
        va_end(vlArgs);
        strcat(strBuffer, "
    ");
        OutputDebugStringA(strBuffer);
        GlobalFree(strBuffer);
        return;
    }
    
    void CreateButton(HWND hwnd)
    {
        HWND hwndPushButton;
        HWND hwndCheckBox;
        HWND hwndRadio;
    
        hwndPushButton = CreateWindow(
            TEXT("button"),
            TEXT("普通按钮"),
            //WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_DEFPUSHBUTTON,
            //WS_CHILD 表示当前按钮是子窗口
            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON| BS_DEFPUSHBUTTON,
            10,
            10,
            80,
            20,
            hwnd,
            (HMENU)1001,            //子窗口ID
            hAppInstance,
            NULL
            );
    
        //获取button的WNDCLASS
        TCHAR szBuffer[0x20];
        GetClassName(hwndPushButton, szBuffer, 0x20);
    
        WNDCLASS wc;
        GetClassInfo(hAppInstance, szBuffer, &wc);
        OutputDebugStringF("-->%s
    ", wc.lpszClassName);
        OutputDebugStringF("-->%x
    ", wc.lpfnWndProc);
    
        hwndCheckBox = CreateWindow (
            TEXT("button"),
            TEXT("复选框"),
            //WS_CHILD | WS_VISIBLE | BS_CHECKBOX | BS_AUTOCHECKBOX,
            WS_CHILD | WS_VISIBLE | BS_CHECKBOX |BS_AUTOCHECKBOX,
            10, 40,
            80, 20,
            hwnd,
            (HMENU)1002,		    //子窗口ID
            hAppInstance,
            NULL);
    
        hwndRadio = CreateWindow (
            TEXT("button"),
            TEXT("单选按钮"),
            //WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON | BS_AUTORADIOBUTTON,
            WS_CHILD | WS_VISIBLE | BS_RADIOBUTTON,
            10, 70,
            80, 20,
            hwnd,
            (HMENU)1003,		    //子窗口ID
            hAppInstance,
            NULL);
    }
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
        hAppInstance = hInstance;
        TCHAR className[] = TEXT("My First Windows");
    
        WNDCLASS wndclass = {0};
        wndclass.hbrBackground = (HBRUSH)COLOR_MENU;
        wndclass.lpfnWndProc = WindowProc;
        wndclass.lpszClassName = className;
        wndclass.hInstance = hInstance;
    
        RegisterClass(&wndclass);
    
        HWND hwnd = CreateWindow(
            className,
            TEXT("我的第一个窗口"),
            WS_OVERLAPPEDWINDOW,
            10,
            10,
            600,
            300,
            NULL,
            NULL,
            hInstance,
            NULL);
    
        if(hwnd == NULL)
            return 0;
    
        CreateButton(hwnd);
    
        ShowWindow(hwnd, SW_SHOW);
    
        MSG msg;
        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
    	return 0;
    }
    
    LRESULT CALLBACK WindowProc(
                                IN  HWND hwnd,
                                IN  UINT uMsg,
                                IN  WPARAM wParam,
                                IN  LPARAM lParam
                                )
    {
        //OutputDebugStringF("%d 
    ", uMsg);//调试查看Windows消息
        switch(uMsg)
        {
        case WM_CREATE:
            {
    //             CREATESTRUCT* p = (CREATESTRUCT*) lParam;
    //             OutputDebugStringF("WM_CREATE: %s 
    ", p->lpszClass);
    //             OutputDebugStringF("WM_CREATE: %d 
    ", uMsg);
                return 0;//这里返回return 0表示消息已经处理过了
            }
        case WM_MOVE:
            {
                //OutputDebugStringF("WM_MOVE: %d 
    ", uMsg);
    
    //             DWORD xPos = (int)(short) LOWORD(lParam);   // horizontal position
    //             DWORD yPos = (int)(short) HIWORD(lParam);   // vertical position
    //
    //             OutputDebugStringF("%d - %d 
    ", xPos, yPos);
    
                return 0;
            }
        case WM_SIZE:
            {
    //             DWORD xWidth = (int)(short) LOWORD(lParam);   // horizontal position
    //             DWORD yHigh = (int)(short) HIWORD(lParam);   // vertical position
    //             OutputDebugStringF("%d - %d 
    ", xWidth, yHigh);
                return 0;
            }
        case WM_KEYUP:
            {
                // OutputDebugStringF("WM_KEYUP %d %d 
    ", wParam, lParam);
                return 0;
            }
        case WM_KEYDOWN:
            {
                // OutputDebugStringF("WM_KEYDOWN %d %d 
    ", wParam, lParam);
                return 0;
            }
        case WM_LBUTTONDOWN:
            {
                OutputDebugStringF("WM_LBUTTONDOWN %d %d 
    ", wParam, lParam);
                return 0;
            }
        case WM_COMMAND:
            {
                switch(LOWORD(wParam))	//LOWORD取低两位的2个字节
                {
                case 1001:
                    MessageBox(hwnd,"Hello Button 1","Demo",MB_OK);
                    return 0;
                case 1002:
                    MessageBox(hwnd,"Hello Button 2","Demo",MB_OK);
                    return 0;
                case 1003:
                    MessageBox(hwnd,"Hello Button 3","Demo",MB_OK);
                    return 0;
                }
                return DefWindowProc(hwnd,uMsg,wParam,lParam);
            }
        case WM_DESTROY://这个是销毁窗口的消息
            {
                //OutputDebugStringF("WM_DESTROY %d %d 
    ",wParam,lParam);
                PostQuitMessage(0);
    
                return 0;
            }
        }
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    

    参考
    https://www.cnblogs.com/furzoom/p/hinstance.html
    https://blog.csdn.net/ljsr123/article/details/104491368

    迷茫的人生,需要不断努力,才能看清远方模糊的志向!
  • 相关阅读:
    CV 第十一课 Segmentation Localization Detection 下
    面经
    overfitting问题
    CV 第十一课 Segmentation Localization Detection 上
    CV 第十一课 Classification + Localization 中
    SVM的特点
    UNSW CV第二课 上 Image Prepocessing
    UNSW CV Assignment1
    UNSW CV 第一课 下 投影 RGB HSV
    HDU 4350
  • 原文地址:https://www.cnblogs.com/autopwn/p/15493308.html
Copyright © 2011-2022 走看看