Windows函数调用

2020-07-01 作者:血花飞舞

从Windows 1.0到Windows 3.1的16位Windows中,MessageBox函数位于动态链接库USER.EXE。在Windows 3.1软件开发套件的WINDOWS.H中,MessageBox函数定义如下:

  1. int WINAPI MessageBox (HWND, LPCSTR, LPCSTR, UINT) ;

注意,函数的第二个、第三个参数是指向常数字符串的指针。当编译连结一个Win16程序时,Windows并不处理MessageBox调用。通过EXE文件中的一张表格,允许Windows将该程序的调用与USER中的MessageBox函数动态链接起来。

32位的Windows除了含有与16位兼容的USER.EXE以外,还含有一个称为USER32.DLL的动态链接库,该动态链接库含有32位使用者接口函数的进入点,包括32位的MessageBox。

这就是Windows支持Unicode的关键:在USER32.DLL中,没有32位MessageBox函数的进入点。实际上,有两个进入点,一个名为MessageBoxA(ASCII版),另一个名为MessageBoxW(宽字符版)。用字符串作参数的每个Win32函数都在操作系统中有两个进入点!幸运的是,您通常不必关心这个问题,程序中只需使用MessageBox。与TCHAR表头文件一样,每个Windows表头文件都有我们需要的技巧。

下面是MessageBoxA在WINUSER.H中定义的方法。这与MessageBox早期的定义很相似:

  1. WINUSERAPI int WINAPI MessageBoxA (HWND hWnd, LPCSTR lpText,
  2. LPCSTR lpCaption, UINT uType) ;

下面是MessageBoxW:

  1. WINUSERAPI int WINAPI MessageBoxW (HWND hWnd, LPCWSTR lpText,
  2. LPCWSTR lpCaption, UINT uType) ;

注意,MessageBoxW函数的第二个和第三个参数是指向宽字符的指针。

如果需要同时使用并分别匹配ASCII和宽字符函数呼叫,那么您可在Windows程序中明确地使用MessageBoxA和MessageBoxW函数。但大多数程序写作者将继续使用MessageBox。根据是否定义了UNICODE,MessageBox将与MessageBoxA或MessageBoxW一样。在WINUSER.H中完成这一技巧时,程序相当琐碎:

  1. #ifdef UNICODE
  2. #define MessageBox MessageBoxW
  3. #else
  4. #define MessageBox MessageBoxA
  5. #endif

这样,如果定义了UNICODE标识符,那么程序中所有对MessageBox函数的调用实际上就是MessageBoxW函数;否则,就是MessageBoxA函数。

执行该程序时,Windows将程序中不同的函数调用与不同的Windows动态链接库的进入点连结。虽然只有少数例外,但是,在Windows 98中不能执行Unicode版的Windows函数。虽然这些函数有进入点,但通常返回错误代码。应用程序注意这些返回的错误并采取一些合理的动作。