(1)第1章对程序错误的处理
[将书上的摘抄一些,便于自己理解]
1. 既然是写程序,就不能避免错误,了解windows的错误处理是debug的必修课,也就是通过错误处理和返回我们能够知道编写的函数运行成还是失败,按照书上所说,微软编译了一个所有可能的错误代码的列表,并且为每个错误代码分配了一个3 2位的号码。
G e t L a s t E r r o r函数:
DWORD GetLastError(); //返回线程的3 2位错误代码
当Wi n d o w s函数运行失败时,应该立即调用G e t L a s t E r r o r函数。如果调用另一个Wi n d o w s函数,它的值很可能被改写。
2. 32位错误代码的域(从高位31到低位0)如下表示:
位 | 31~30 | 29 | 28 | 27~16 | 15~0 |
内容含义 | 严重性 0=成功 1=供参考 2=警告 3=错误 | 0=微软定义的代码 1=客户定义的代码 | 保留 必须是0 | 设备代码 微软定义 | 异常代码 微软定义 |
3.查看错误代码含义的示例
书上的是c++的,MFC一贯让我很迷糊,所以后续示例都用delphi重写.
unit UnitErrorShow; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TFormErrorShow = class(TForm) Label1: TLabel; EditCode: TEdit; chkTop: TCheckBox; MemoShow: TMemo; btnLookup: TButton; procedure btnLookupClick(Sender: TObject); procedure chkTopClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var FormErrorShow: TFormErrorShow; implementation {$R *.dfm} function MAKELANGID(_p, _s: Word): DWORD; begin Result := (_s shl 10) or (_p); end; procedure TFormErrorShow.btnLookupClick(Sender: TObject); var dwError: DWORD; hlocal: THandle; fOk: DWORD; hDll: HMODULE; begin MemoShow.Clear; hlocal := 0; try dwError := StrToInt(EditCode.Text); except ShowMessage('输入有错误,请输入数字!'); EditCode.SetFocus; end; fOk := FormatMessage(// FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_ALLOCATE_BUFFER, // nil, // dwError, // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // PChar(@hlocal), // 0, // nil); //ShowMessage(IntToStr(hlocal)); {判断是否为网络相关错误} if (fOk = 0) then begin hDll := LoadLibraryEx('netmsg.dll', 0, DONT_RESOLVE_DLL_REFERENCES); if (hDll <> 0) then begin FormatMessage(// FORMAT_MESSAGE_FROM_HMODULE or FORMAT_MESSAGE_FROM_SYSTEM, // @hDll, // dwError, // MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), // PChar(@hlocal), // 0, // nil); FreeLibrary(hDll); end; end; if hlocal <> 0 then begin MemoShow.Lines.Add(PChar(LocalLock(hlocal))); LocalFree(hlocal); end else begin MemoShow.Lines.Add('不可识别的错误代码!'); end; end; procedure TFormErrorShow.chkTopClick(Sender: TObject); begin if chkTop.Checked = True then Self.FormStyle := fsStayOnTop else Self.FormStyle := fsNormal; end; end.
[摘录]如果F o r m a t M e s s a g e函数运行成功,那么错误代码的文本描述就位于内存块中,将它拷贝到对话框底部的滚动窗口中。如果F o r m a t M e s s a g e函数运行失败,设法查看N e t M s g . d l l模块中的消息代码,以了解该错误是否与网络有关。使用N e t M s g . d l l 模块的句柄,再次调用F o r m a t M e s s a g e函数。
这样重写以后,思路清晰了很多,但是有一个问题,我没有在delphi中找到MAKELANGID函数(看来对delphi的函数还需要下大功夫),在VS中,它定义的是一个宏,因此只能自己写一个函数.后边还会有很多的需要转换的东西,感觉VCL确实比MFC要好用,至少在一般的win32程序中,我会首选VCL,这样也有一个好处,如果用的是VC,那么我或许只是照抄了一边,但现在,我需要面对可能出现的变量重定义问题,无形之中就把delphi中的东西也过了一边,加深了印象.