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 Files\Microsoft Visual Studio\VC98\Include\WINDEF.H
DECLARE_HANDLE(HINSTANCE);

image

  • (4) 看到前面定義的是DECLARE_HANDLE,再次F12進去看看具體代碼,得到如下位置:C:\Program Files\Microsoft Visual Studio\VC98\Include\WINNT.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 Files\Microsoft Visual Studio\VC98\Include\WINDEF.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, "\n");
    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\r\n", wc.lpszClassName);
    OutputDebugStringF("-->%x\r\n", 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 \r\n", uMsg);//調試查看Windows消息
    switch(uMsg)
    {
    case WM_CREATE:
        {
//             CREATESTRUCT* p = (CREATESTRUCT*) lParam;
//             OutputDebugStringF("WM_CREATE: %s \r\n", p->lpszClass);
//             OutputDebugStringF("WM_CREATE: %d \r\n", uMsg);
            return 0;//這里返回return 0表示消息已經處理過了
        }
    case WM_MOVE:
        {
            //OutputDebugStringF("WM_MOVE: %d \r\n", uMsg);

//             DWORD xPos = (int)(short) LOWORD(lParam);   // horizontal position
//             DWORD yPos = (int)(short) HIWORD(lParam);   // vertical position
//
//             OutputDebugStringF("%d - %d \r\n", 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 \r\n", xWidth, yHigh);
            return 0;
        }
    case WM_KEYUP:
        {
            // OutputDebugStringF("WM_KEYUP %d %d \r\n", wParam, lParam);
            return 0;
        }
    case WM_KEYDOWN:
        {
            // OutputDebugStringF("WM_KEYDOWN %d %d \r\n", wParam, lParam);
            return 0;
        }
    case WM_LBUTTONDOWN:
        {
            OutputDebugStringF("WM_LBUTTONDOWN %d %d \r\n", 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 \r\n",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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM