Microsoft KB Archive/241391

= HOWTO: Use the Win32 API FormatMessage Function with Visual FoxPro =

Article ID: 241391

Article Last Modified on 7/13/2004

-

APPLIES TO


 * Microsoft Visual FoxPro 5.0 Standard Edition
 * Microsoft Visual FoxPro 5.0a
 * Microsoft Visual FoxPro 6.0 Professional Edition

-



This article was previously published under Q241391



SUMMARY
Visual FoxPro developers often incorporate calls to Win32 API functions in order to extend their applications. Sometimes, these calls fail. Using a combination of the Win32 API functions GetLastError and FormatMessage, developers can display both a numeric and text message detailing why the call failed. This article demonstrates how.



MORE INFORMATION
To run this sample, copy the following code into a new Visual FoxPro program, save and run it. You can adjust the value of the lnApiToCall variable (top of program) to call one of three different Win32 API functions and get different errors from FormatMessage: *!* The following code makes calls to one of three different Win32 API functions. LOCAL lnAPIToCall lnAPIToCall = 1
 * !* The calls will fail. The function that is called is determined
 * !* by the value of "lnAPIToCall". Change the value of "lnAPIToCall"
 * !* to see different error messages:
 * !* lnAPIToCall = 1: GetSysColor is called.
 * !* lnAPIToCall = 2: GetUserName is called.
 * !* lnAPIToCall = 3: FindWindow is called.


 * !* #DEFINES from HOME+"FOXPRO.h"
 * 1) DEFINE MB_ICONINFORMATION     64      && Information message
 * 2) DEFINE MB_OK                  0       && OK button only


 * 1) DEFINE CR                     CHR(13) && Carriage Return
 * 2) DEFINE ERROR_SUCCESS          0       && Success error code from WINERROR.H
 * 3) DEFINE FORMAT_MESSAGE_FROM_SYSTEM    0x00001000 && Value for use with FormatMessage API. From WINBASE.H

DECLARE INTEGER GetLastError IN win32api
 * !* Declare function to return system error code if an API call fails.

DECLARE INTEGER FormatMessage IN kernel32.DLL ; INTEGER dwFlags, ; STRING @lpSource, ; INTEGER dwMessageId, ; INTEGER dwLanguageId, ; STRING @lpBuffer, ; INTEGER nSize, ; INTEGER Arguments
 * !* Declare function to return text message from system error code.


 * !* Now declare three Win32 API functions:
 * !* GetSysColor, GetUserName and GetWindow.
 * !* Later, you will make calls to these functions that will fail
 * !* and use GetLastError and FormatMessage to display why.
 * !* For more information on the use of these functions in FoxPro,
 * !* see the References section at the bottom of this article

DECLARE INTEGER GetSysColor IN User32.DLL INTEGER
 * !* The GetSysColor function retrieves the current color
 * !* of the specified display element. Display elements are
 * !* the parts of a window and the display that appear
 * !* on the system display screen.

DECLARE INTEGER GetUserName IN Win32API ; STRING @lpBuffer, ; INTEGER @nSize
 * !* The GetUserName function retrieves the user
 * !* name of the current thread. This is the name
 * !* of the user currently logged onto the system.

DECLARE INTEGER GetWindow ; IN win32api ; INTEGER HWND, ; INTEGER uCmd
 * !* The GetWindow function retrieves a handle to a
 * !* window that has the specified relationship
 * !* (Z order or owner) to the specified window.


 * !*  END OF DECLARES

LOCAL lnSuccess lnSuccess = 0
 * !* Set up the return value variable for the API calls (lnSuccess)

DO CASE CASE lnAPIToCall = 1 lnSuccess = GetSysColor(99) CASE lnAPIToCall = 2 LOCAL lpBuffer,nBufferSize lpBuffer = SPACE(25) && Return buffer for user ID string nSize = 1           && Size of user ID return buffer lnSuccess = GetUserName(@lpBuffer,@nSize) CASE lnAPIToCall = 3 lnSuccess = GetWindow(99,2) OTHERWISE =MESSAGEBOX("There is no API call associated with that value",MB_ICONINFORMATION+MB_OK,"ERROR") RETURN .F. ENDCASE
 * !*    This call will fail because 99 is in invalid parameter. For a list of valid
 * !*    parameters to use with GetSysColor, see Q139291.
 * !*    This call will fail because you misreport the size of the buffer (nSize). Should be 25.
 * !*    This call will fail because you pass an invalid window handle (first parameter).

IF !(lnSuccess > ERROR_SUCCESS) lpBuffer = SPACE(128) lnError = GetLastError =FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, ;       'WINERROR.H', lnError, 0, @lpBuffer, 128, 0)
 * !*     The API call failed. So, you put up a messagebox saying so
 * !*     and display the system error code from WINERROR.H. You extend this
 * !*     by using FormatMessage API to display a character error message.
 * !*     One thing to note here is that the error codes for the three calls
 * !*     used above are stored in WINERROR.H. As such, that header file name
 * !*     is hard-coded into the FormatMessage call. This may need to be
 * !*     adjusted depending on the APIs used.
 * !*     adjusted depending on the APIs used.

=MESSAGEBOX("System error has occurred." + CR + ;       "System Error code: " + ALLTRIM(STR(lnError)) + CR + ;        "System Error message: "+ALLT(lpBuffer),MB_ICONINFORMATION+MB_OK,"ERROR") ENDIF (c) Microsoft Corporation 1999, All Rights Reserved. Contributions by Trevor Hancock, Microsoft Corporation.

