(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重写.

1

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中的东西也过了一边,加深了印象.

posted @ 2017-10-15 17:06  陨落流星  阅读(713)  评论(0编辑  收藏  举报