在Win32編程時不免會出現錯誤,最頭痛的就是不知道錯哪裡,為什麼會錯,微軟同樣想到這個事情,為此,提供了一個不錯的函數GetLastError(),此函數可以返回上一次出錯的錯誤碼。
比如下面這段代碼:
#include<windows.h>
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
return DefWindowProc(hwnd,message,wParam,lParam);
}
BOOL InitApp(HINSTANCE hInstance,WNDCLASS *wndclass)
{
wndclass->cbClsExtra=0; //無附加視窗類別記憶體
wndclass->cbWndExtra=0; //無附加視窗記憶體
wndclass->hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass->hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass->hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass->hInstance=hInstance;
wndclass->lpfnWndProc=WndProc;
wndclass->lpszClassName=TEXT("NewStart");
wndclass->lpszMenuName=NULL;
wndclass->style=WS_HSCROLL|CS_HREDRAW; //應該這裡故意寫錯 但是編譯能過
return RegisterClass(wndclass);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
char buf[500];
BOOL fOK;
HWND hwnd;
DWORD dwErr,systemLocale;
HLOCAL hLocal=NULL;
MSG msg;
WNDCLASS wndclass;
int flag;
if(InitApp(hInstance,&wndclass)==NULL)
{
dwErr=GetLastError();
wsprintf(buf,L"%d",dwErr);
MessageBox(NULL,buf,TEXT("Error Report"),MB_OK);
return 0;
}
hwnd=CreateWindow(TEXT("NewStart"),TEXT("Hello!"),WS_SYSMENU|WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,400,300,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,nShowCmd);
UpdateWindow(hwnd);
while((flag=GetMessage(&msg,hwnd,0,0))!=0&&flag!=-1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
GetLastError()會返回一個錯誤號碼 87 然後你可以通過msdn查到這個錯誤編號的意思為 參數不正確 的確是這樣的,並且如果你調試這段代碼查看$err或者是dwErr都可以得到這個錯誤編號,如果你在這些變數後加上,hr可以得到87對應的錯誤解釋
當你想讓程式執行過程中顯示錯誤解釋,那就要用到另一個函數FormatMessage(),代碼如下:
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
char buf[500];
BOOL fOK;
HWND hwnd;
DWORD dwErr,systemLocale;
HLOCAL hLocal=NULL;
MSG msg;
WNDCLASS wndclass;
int flag;
if(InitApp(hInstance,&wndclass)==NULL)
{
dwErr=GetLastError();
systemLocale=MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL);
fOK=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,dwErr,systemLocale,(LPWSTR)&hLocal,0,NULL);
MessageBox(NULL,(LPCWSTR)LocalLock(hLocal),TEXT("hello"),MB_OK);
return 0;
}
hwnd=CreateWindow(TEXT("NewStart"),TEXT("Hello!"),WS_SYSMENU|WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,400,300,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,nShowCmd);
UpdateWindow(hwnd);
while((flag=GetMessage(&msg,hwnd,0,0))!=0&&flag!=-1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
這裡要解釋一些東西:
HLOCAL是一個指向記憶體塊的控制代碼,初始化為0;
MAKELANGID在msdn上的解釋是This macro creates a language identifier from a primary language identifier and a sub-language identifier.
就是可以通過這個函數建立語言標示符,而他有2個參數,第一語言標示符和子語言標示符,我們這裡的LANG_NEUTRAL,SUBLANG_NEUTRAL聯合放在一起的值等於0,也就是作業系統的預設語言。
FORMAT_MESSAGE_FROM_SYSTEM:這個宏是告訴FormatMessage,我們希望獲得一個與一個系統定義的錯誤碼對應額字串。
FORMAT_MESSAGE_IGNORE_INSERTS:這個宏允許我們獲得含有%預留位置的訊息。
FORMAT_MESSAGE_ALLOCATE_BUFFER: 這個宏告訴該函數分配一足夠容納錯誤文本描述的記憶體。
FormatMessage將錯誤資訊存在hLocal處。
FormatMessage這個函數其實功能很強大,其他具體的用法建議看msdn:http://msdn.microsoft.com/en-us/library/ms679351(VS.85).aspx
LocalLock() msdn上的解釋為Locks a local memory object and returns a pointer to the first byte of the object's memory block。
也就是說這個函數可以用來鎖定一個記憶體對象,並且返回這項這個對象記憶體塊的首地址。
#include <Windows.h>//using namespace std;LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){return DefWindowProc(hwnd,message,wParam,lParam);}BOOL InitApp(HINSTANCE hInstance , WNDCLASS *wndclass){wndclass->cbClsExtra = 0; //無附加視窗類別記憶體wndclass->cbWndExtra = 0; //無附加視窗類別記憶體wndclass->hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wndclass->hCursor = LoadCursor(NULL,IDC_ARROW);wndclass->hIcon = LoadIcon(NULL,IDI_APPLICATION);wndclass->hInstance = hInstance;wndclass->lpfnWndProc = WndProc;wndclass->lpszClassName = TEXT("NewStart");wndclass->lpszMenuName = NULL;wndclass->style = WS_HSCROLL | CS_HREDRAW;return RegisterClass(wndclass);}int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){TCHAR buf[80];BOOL fOK;HWND hwnd;DWORD dwErr,LanguageID;HLOCAL hLocal = NULL;MSG msg;WNDCLASS wndclass;int flag;if(NULL == InitApp(hInstance,&wndclass)){dwErr = GetLastError();/*wsprintf(buf,L"%d",dwErr);MessageBox(NULL,buf,TEXT("Error Report"),MB_OK);*/LanguageID = MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL); // default languagefOK = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,NULL,dwErr,LanguageID,(LPWSTR)&hLocal,0,NULL);//MessageBox(NULL,(LPCWSTR)LocalLock(hLocal),TEXT("Hello"),MB_OK);wsprintf(buf,L"Error Info. ( Error code Number = %d) : %s",dwErr,LocalLock(hLocal));LocalFree(hLocal); // 一定要記得當hLocal所指向的記憶體不用了的時候就要用localFree來釋放掉,否則會造成記憶體泄露!MessageBox(NULL,buf,TEXT("Error Report"),MB_OK);return (0);}hwnd = CreateWindow(TEXT("NewStart"),TEXT("Hello"),WS_SYSMENU | WS_VISIBLE,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);ShowWindow(hwnd,SW_SHOWNORMAL);UpdateWindow(hwnd);while(0 != (flag = GetMessage(&msg,NULL,NULL,NULL))&& flag !=-1){TranslateMessage(&msg);DispatchMessage(&msg);}return msg.wParam;}
輸出:Error Info. ( Error code Number = 87) : 參數出錯。