FormatMessage函数的用法

使用FormatMessage时如果对一些参数不仔细研究,那么就会出错误,首先说下这个函数

1 函数描述

DWORD WINAPI FormatMessage(
  _In_      DWORD dwFlags,
  _In_opt_  LPCVOID lpSource,
  _In_      DWORD dwMessageId,
  _In_      DWORD dwLanguageId,
  _Out_     LPTSTR lpBuffer,
  _In_      DWORD nSize,
  _In_opt_  va_list *Arguments
);

<1>dwFlags

格式化选项,这个参数主要用来影响lpSource以及lpBuffer,需要注意的是FORMAT_MESSAGE_ALLOCATE_BUFFER,当指定它的时候,是系统为你分配内存,这个时候的lpBuffer参数需要做一些处理,如果传递的是LPSTR buf的话,则传递的参数应该是&buf(这里涉及到了函数栈的销毁问题,在《C++高质量编程中有过》解释);如果没有指定FORMAT_MESSAGE_ALLOCATE_BUFFER的话,那么传递的就是一个字符数组。

<2>lpSource

消息定义的位置,依赖于dwFlags的设置,有两种情况

FORMAT_MESSAGE_FROM_HMODULE:

0x00000800 A handle to the module that contains the message table to search.

FORMAT_MESSAGE_FROM_STRING:

0x00000400 Pointer to a string that consists of unformatted message text. It will be scanned for inserts and formatted accordingly.

如果这两个都没有指定的话,那么lpSource参数就会被忽略

<3>dwMessageId

错误ID,如果dwFlags中指定了FORMAT_MESSAGE_FROM_STRING,那么该值就会被忽略

<4>dwLanguageId

语言ID,如果如果dwFlags中指定了FORMAT_MESSAGE_FROM_STRING,那么该值就会被忽略。

MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)	//设置为本地默认语言
MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US)	//设置为美语
MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)	//中文简体

所有的语言宏定义都是在WinNT.h中可以看到。

<5>lpBuffer

输出的缓冲区,注意事项在dwFlags中说了,主要是依据FORMAT_MESSAGE_ALLOCATE_BUFFER来相应变化

<6>nSize

输出缓冲区的大小,如果没有指定FORMAT_MESSAGE_ALLOCATE_BUFFER,则是缓冲区自身的大小,如果指定了

FORMAT_MESSAGE_ALLOCATE_BUFFER,可以随意设置,设置为0也没事。

<7>Arguments

这个参数第一次是用的时候感觉是尤其复杂。这个参数跟dwFlags,lpSource都有关系,所以才是有点复杂。参数类型是va_list*,首先如果参数不是一个va_list*的指针,那么就得在dwFlags中使用FORMAT_MESSAGE_ARGUMENT_ARRAY ,并且传递一个DWORD_PTR类型的数组作为参数。

%n!string!的用法:

其中n是1-99的整数,如果不加后面的!string!的话就直接表示第一个,第二个参数,以此类推。

当加上!string!时,要注意中间的string是有一个*还是有两个*,在指定FORMAT_MESSAGE_ARGUMENT_ARRAY的时候,一个*则下一个元素是n+2,两个*的话就是n+3。在没有指定FORMAT_MESSAGE_ARGUMENT_ARRAY 的情况下,一个*就是n+1,两个星就是n+2.

例如:

LPWSTR pMessage = L"%1!*.*s! %4 %5!*s!";
	DWORD_PTR pArgs[] = { (DWORD_PTR)4, (DWORD_PTR)1, (DWORD_PTR)L"Bill",
         (DWORD_PTR)L"Bob", (DWORD_PTR)5, (DWORD_PTR)L"Bill" };
    	const DWORD size = 100+1;
    	WCHAR buffer[size];

    if (!FormatMessageW(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                       pMessage,
                       0,
                       0,
                       buffer,
                       size,
                       (va_list*)pArgs))
    {
        wprintf(L"Format message failed with 0x%x\n", GetLastError());
        return;
    }

这里面pArgs的4代表第一个插入元素的宽度,1代表精度(即Bill中的一个元素B)。6代表元素的宽度,每一个字符串之间都是以空格为间隔,上面的程序运行得到的buffer就是“    B Bob  Bill”

7 再看两个例子区分下

<1>

LPSTR buf;
	LONG x1 = RegCreateKey(HKEY_LOCAL_MACHINE,TEXT("sofware\\VC++MFC\\adminss"),&hKey);
	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER |
		FORMAT_MESSAGE_FROM_SYSTEM,
		NULL ,
		x1,
		MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
		(LPTSTR)&buf,
		3,
		NULL);
	LocalFree(buf);

注意这里buf以及参数dwFlags

<2>

TCHAR buf[100] = {0};
	LONG x1 = RegCreateKey(HKEY_LOCAL_MACHINE,TEXT("sofware\\VC++MFC\\adminss"),&hKey);
	FormatMessage(
		FORMAT_MESSAGE_FROM_SYSTEM,
		NULL ,
		x1,
		MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
		(LPTSTR)buf,
		100,
		NULL);

注意这里的buf以及参数dwFlags

8 VS提供的查看错误的工具

VS,工具-》错误查找,就可以打开错误对话框,然后在Key中输入值就可以查找错误ID对应的文字描述了。这里的错误ID是可以是10进制,也可以是16进制,但是不管10进制还是16进制,只要其对应的值相等那么错误描述就一样。

FormatMessage函数的用法

时间: 2024-09-30 06:45:00

FormatMessage函数的用法的相关文章

mysql中计算两个日期的时间差函数TIMESTAMPDIFF用法

mysql中计算两个日期的时间差函数TIMESTAMPDIFF用法: 语法: TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2) 说明: 返回日期或日期时间表达式datetime_expr1 和datetime_expr2the 之间的整数差.其结果的单位由interval 参数给出.interval 的法定值同TIMESTAMPADD()函数说明中所列出的相同. mysql> SELECT TIMESTAMPDIFF(MONTH,'200

【转】oracle的substr函数的用法

[转]oracle的substr函数的用法 oracle的substr函数的用法 取得字符串中指定起始位置和长度的字符串   substr( string, start_position, [ length ] ) 如:     substr('This is a test', 6, 2)     would return 'is'     substr('This is a test', 6)     would return 'is a test'     substr('TechOnThe

Oracle trunc()函数的用法

--Oracle trunc()函数的用法 /**************日期  TRUNC()函数没有秒的精确 ********************/ select sysdate from dual --当时日期 select trunc(sysdate) from dual select trunc(sysdate ,'DD') from dual --今天日期 select trunc(sysdate,'d')+7 from dual --本周星期日 select trunc(sys

C中的时间函数的用法

C中的时间函数的用法    这个类展示了C语言中的时间函数的常用的用法. 源代码: #include <ctime>#include <iostream> using namespace std; class MyTime{public:    MyTime() { mPTime = 0; mStLocalTime = 0; mStGMTTime = 0; }    ~MyTime() {}; //time_t time(time_t * timer) 返回自1970年1月1日00

嵌入式之---常用模板函数(用法说明函数、参数解析函数)

主要内容:嵌入式常用模板函数(用法说明函数.参数解析函数) /*显示参数列表*/ void usage() {     printf("usage: server [-p:x] [-i:IP] [-o]\n\n");     printf("       -p:x      Port number to listen on\n");     printf("       -i:str    Interface to listen on\n");

awk中split函数的用法

The awk function split(s,a,sep) splits a string s into an awk array a using the delimiter sep. time=12:34:56 echo $time | awk '{split($0,a,":" ); print a[1]}' 12   echo $time | awk '{split($0,a,":" ); print a[3]}' 34   echo $time | awk

ecl函数的用法

相关函数 fork, execle, execlp, execv, execve, execvp Windows下头文件 #include <process.h> Linux下头文件 #include <unistd.h> 函数定义 int execl(const char *path, const char *arg, ...); 函数说明 execl()其中后缀"l"代表list也就是参数列表的意思,第一参数path字符指针所指向要执行的文件路径, 接下来的

setdefault函数的用法及个人理解

setdefault函数的用法及理解dict.setdefault(key, default=None) 功能:如果键不存在于字典中,将会添加该键并将default的值设为该键的默认值,如果键存在于字典中,将读出该键原来对应的值,default的值不会覆盖原来已经存在的键的值. 参数:key----要查找的键default-----查找的键不存在时用于设置的默认值 使用方法示例:(以下使用方法是我理解setdefault函数的过程)方法一:给字典中不存在的键赋值为默认值None>>> E

Oracle to_date()函数的用法《转载》

to_date()是Oracle数据库函数的代表函数之一,下文对Oracle to_date()函数的几种用法作了详细的介绍说明, 原文地址:http://database.51cto.com/art/201010/231193.htm 在Oracle数据库中,Oracle to_date()函数是我们经常使用的函数,下面就为您详细介绍Oracle to_date()函数的用法,希望可以对您有所启迪. to_date()与24小时制表示法及mm分钟的显示: 一.在使用Oracle的to_date