Windows客户端开发--必须清楚HWND、HANDLE、HMODULE、HINSTANCE的区别

本文深入探讨了Windows编程中常见的四种句柄类型:HWND、HANDLE、HMODULE与HINSTANCE的区别及用法。通过代码实例展示了这些句柄在查找窗口、单例运行、获取文件大小等应用场景中的具体实现。
我先不说话,就看看几个代码片段

1 使用HWND
查找窗口:

HWND h_wnd = ::FindWindow(_T("MainForm"), NULL);

创建窗口:

HWND hwnd = WindowEx::Create(NULL, L"", WS_POPUP, WS_EX_TOOLWINDOW);

2 使用HANDLE
单例运行:

bool SingletonRun(const wchar_t *application)
{
    assert(application);
    if (application == NULL)
        return false;

    HANDLE hMutex = ::CreateMutexW(NULL, TRUE, application);

    if (hMutex == NULL)
        return false;

    if (::GetLastError() == ERROR_ALREADY_EXISTS)
    {
        ::CloseHandle(hMutex);
        return false;
    }

    /* 从此这个互斥信号量就被不受控地打开了,直到进程退出 */
    return true;
}

获取文件大小:

int64_t GetFileSize(const PathString &filepath)
{
    WIN32_FIND_DATAW file_data;
    HANDLE file = FindFirstFileW(filepath.c_str(), &file_data);

    if (file == INVALID_HANDLE_VALUE)
        return -1;
    LARGE_INTEGER li = { file_data.nFileSizeLow, file_data.nFileSizeHigh };
    FindClose(file);
    return li.QuadPart;
}

3 使用HMODULE
动态加载dll:

HMODULE moudle_handle = ::LoadLibraryW(L"shell32.dll");

获取模块directory:

std::wstring GetModuleDirectory(HMODULE module_handle)
{
    //DCHECK(IsModuleHandleValid(module_handle));
    std::wstring module_directory;
    if (FilePathApartDirectory(GetModulePathName(module_handle), module_directory))
        return module_directory;
    return L"";
}

4 使用HINSTANCE
打开目录:

HINSTANCE inst = ::ShellExecute(NULL, L"open", dir.c_str(), NULL, NULL, SW_SHOW);
Windows上如何定义的

1 HWND
A handle to a window

typedef HANDLE HWND;

2 HANDLE
A handle to an object

typedef PVOID HANDLE;

3 HMODULE
A handle to a module. This is the base address of the module in memory.

typedef HINSTANCE HMODULE;

看到定义了,答案很明了:
HMODULE 和 HINSTANCE 只有在16位的windows系统上才有区别,否则没有区别。

4 HINSTANCE
A handle to an instance. This is the base address of the module in memory.

typedef HANDLE HINSTANCE;

此时此刻,不知道你懵逼了没有,反正我是懵了,看定义,HWND、HANDLE、HMODULE、HINSTANCE这四个东西不是一样的吗!!!!

也就是可以说 HWND、HANDLE、HMODULE、HINSTANCE之间的差别不是在变量类型上,而是在语义上。

到底有什么区别?

HWND是线程相关的,你可以通过HWND找到该窗口所属进程和线程

Handle 是代表系统的内核对象,如文件句柄,线程句柄,进程句柄。
系统对内核对象以链表的形式进行管理,载入到内存中的每一个内
核对象都有一个线性地址,同时相对系统来说,在串列中有一个索引位置,这个索引位置就是内核对象的handle。

HINSTANCE的本质是模块基地址,他仅仅在同一进程中才有意义,跨进程的HINSTANCE是没有意义

HMODULE 是代表应用程序载入的模块,win32系统下通常是被载入模块的线性地址。

HINSTANCE 在win32下与HMODULE是相同的东西(只有在16位windows上,二者有所不同).

<think>在Windows编程中,`HMODULE`是一个重要的数据类型,它代表一个模块(module)的句柄(handle)。模块可以是应用程序自身(.exe)或动态链接库(.dll)。`HMODULE`实际上是一个指向模块基地址的指针,用于在程序中标识和操作模块。###1.**`HMODULE`的定义**在Windows头文件中,`HMODULE`通常定义如下:```cpptypedefHINSTANCEHMODULE;```而`HINSTANCE`实际上是一个指向模块基地址的指针,通常定义为:```cpptypedefHANDLEHINSTANCE;```最终,`HANDLE`是一个`void*`类型的指针,即:```cpptypedefvoid*HANDLE;```因此,`HMODULE`本质上是一个`void*`指针,指向模块在内存中的基地址。###2.**`HMODULE`的获取**在Windows编程中,可以通过以下函数获取`HMODULE`:-**`GetModuleHandle`**:获取一个已经加载到进程地址空间中的模块的句柄。```cppHMODULEGetModuleHandle(LPCTSTRlpModuleName);```如果参数为`NULL`,则返回当前进程的句柄(即.exe文件的模块句柄)。-**`LoadLibrary`**:加载一个模块(DLL)到进程地址空间,并返回其句柄。```cppHMODULELoadLibrary(LPCTSTRlpFileName);```如果加载失败,返回`NULL`。###3.**`HMODULE`的使用**获得模块句柄后,可以用于:-**获取模块中的函数地址**:使用`GetProcAddress`函数。```cppFARPROCGetProcAddress(HMODULEhModule,LPCSTRlpProcName);```-**获取模块的文件路径**:使用`GetModuleFileName`函数。```cppDWORDGetModuleFileName(HMODULEhModule,LPTSTRlpFilename,DWORDnSize);```-**卸载模块**:使用`FreeLibrary`函数。```cppBOOLFreeLibrary(HMODULEhModule);```###4.**示例代码**以下是一个简单的示例,展示如何使用`HMODULE`加载一个DLL,并调用其中的函数:```cpp#include<iostream>#include<windows.h>intmain(){//加载DLLHMODULEhModule=LoadLibrary(TEXT("MyDll.dll"));if(hModule==NULL){std::cerr<<"LoadLibraryfailed:"<<GetLastError()<<std::endl;return1;}//获取DLL中的函数地址typedefvoid(*MyFunc)();MyFuncpFunc=(MyFunc)GetProcAddress(hModule,"MyFunction");if(pFunc==NULL){std::cerr<<"GetProcAddressfailed:"<<GetLastError()<<std::endl;FreeLibrary(hModule);return1;}//调用函数pFunc();//卸载DLLFreeLibrary(hModule);return0;}```###5.**注意事项**-**内存管理**:使用`LoadLibrary`加载的模块在使用完毕后必须调用`FreeLibrary`释放,否则会导致资源泄漏。-**错误处理**:调用这些API后,应检查返回值并使用`GetLastError`获取错误代码。-**字符编码**:WindowsAPI有ANSI(`A`后缀)和Unicode(`W`后缀)版本,建议使用Unicode版本(如`LoadLibraryW`)或在项目中设置使用Unicode字符集。###总结`HMODULE`是Windows编程中用于表示模块句柄的数据类型,它允许程序动态加载和操作DLL,调用其中的函数,以及获取模块信息。正确使用`HMODULE`及相关API是Windows动态链接库编程的基础。§§相关问题§§:1.什么是`HINSTANCE`?它与`HMODULE`有何区别?2.在Windows中,如何获取当前进程的模块句柄?3.使用`GetProcAddress`时,如何避免函数名或函数指针类型错误导致的崩溃?4.在动态加载DLL时,除了`LoadLibrary`和`FreeLibrary`,还有哪些重要的API函数?</think>### 关于 `HMODULE` 的解释 `HMODULE` 是 Windows API 中用于表示**模块句柄**的数据类型,在 C++ 的 Windows 编程中至关重要。以下是详细解释: #### 1. **定义与本质** - **定义**:`typedef HANDLE HMODULE;` - **实质**:指向内存中模块基地址的指针(`void*` 类型) - **代表对象**: - 可执行文件(`.exe`) - 动态链接库(`.dll`) - 其他系统模块(如 `.ocx`) #### 2. **核心作用** 1. **模块标识**:唯一标识加载到进程内存中的模块 2. **资源访问**:用于访问模块中的函数/资源(如 `GetProcAddress`) 3. **生命周期管理**:配合 `LoadLibrary`/`FreeLibrary` 管理模块加载状态 #### 3. **关键 API 函数** ```cpp // 加载模块(返回 HMODULEHMODULE LoadLibrary(LPCTSTR lpFileName); // 获取已加载模块的句柄 HMODULE GetModuleHandle(LPCTSTR lpModuleName); // 从模块获取函数地址 FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName); // 卸载模块 BOOL FreeLibrary(HMODULE hModule); ``` #### 4. **使用示例** ```cpp #include <Windows.h> #include <iostream> int main() { // 加载 User32.dll HMODULE hUser32 = LoadLibrary(TEXT("User32.dll")); if (!hUser32) { std::cerr << "LoadLibrary failed: " << GetLastError() << "\n"; return 1; } // 获取 MessageBoxA 函数地址 using MessageBoxFunc = int(WINAPI*)(HWND, LPCSTR, LPCSTR, UINT); auto MessageBoxA = reinterpret_cast<MessageBoxFunc>( GetProcAddress(hUser32, "MessageBoxA")); if (MessageBoxA) { MessageBoxA(nullptr, "Hello from DLL!", "HMODULE Demo", MB_OK); } else { std::cerr << "GetProcAddress failed: " << GetLastError() << "\n"; } // 卸载模块 FreeLibrary(hUser32); return 0; } ``` #### 5. **特殊值含义** - **`NULL` 句柄**:表示当前进程的可执行模块 ```cpp // 获取当前 .exe 的路径 TCHAR exePath[MAX_PATH]; GetModuleFileName(NULL, exePath, MAX_PATH); ``` #### 6. **内存布局意义** 当模块加载时,系统为其分配内存基址: ``` 0x00007FFA`3D4A0000 // 示例基址 (HMODULE 值) ├── 导出函数表 ├── 资源段 └── 代码/数据段 ``` #### 7. **注意事项** 1. **资源泄漏**:忘记调用 `FreeLibrary` 会导致模块滞留内存 2. **无效句柄**:卸载后继续使用 `HMODULE` 会引发访问冲突 3. **多线程同步**:跨线程传递 `HMODULE` 需确保模块未提前卸载 4. **ANSI/Unicode**:函数有 `A`/`W` 版本(如 `GetModuleFileNameA/W`) ### 总结 `HMODULE` 是 Windows 模块化编程的核心句柄类型,它作为模块在内存中的唯一标识符,使开发者能够动态加载/卸载代码、访问导出函数和资源。正确管理其生命周期(加载→使用→卸载)对构建稳定应用至关重要。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一苇渡江694

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值