Ten advice of Windows CE programming
Reference from: http://www.chinabyte.com/softchannel/72342371878043648/20031202/1749567_2.shtml
[Article] Author: Unknown Date: 2003-12-02 Source: Research Network Embedded Editor: Ark [article REVIEW] This article is summed up based on the experience of writing Raima Data Manager on Windows CE, CE worth developing Personnel learn from
[Text] In the last two weeks, we spent most of the time to transplant existing applications into Microsoft Windows CE. Generally speaking, this plan is not too difficult. We started to Microsoft Win32 code, and of course Windows CE is a Win32 application interface (API). Advantageously, our application (ie RAIMA Data Manager) has a convenient use interface and contains a library consisting of approximately 150 sub-functions, which are written by C language, which can be used to create, manage, and access. database.
According to the way of establishing an application, we originally ported it into Windows CEs and is a relatively simple C language programming practice. However, we have encountered some difficulties soon. Starting from a careless mistake, such as using the Microsoft Windows NT library on Windows NT-based Windows CE emulators, then violate Windows CE programming arms, such as "Don't give Unicode (International Standards Organization 10646 standard) character assignment odd numbers Memory address.
About 90% of the problem is more or less related to Unicode. Although Unicode programming is not difficult, it is easy to make an error when writing code to the single-byte character (I have many mistakes).
The following advice is based on our experience in writing RAIMA Data Manager on Windows CE, but I believe that they are worth learning from any other Windows CE program. After all, most of the Windows developers, when they create the first Windows CE application, truly use the win32 knowledge that has been mastered.
1. Do not use the Windows NT library on the emulator
The first mistake discussed here is too stupid, but I still can't fall in, maybe you will. When you create a Windows CE program with Microsoft VC (version 5.0), you will find that the path (INCLUDE), library path (library), and executable path are automatically adjusted to match the choice of response target environment. Therefore, if you establish an application for the Windows CE emulator, you will find that the include path does not point to the win32 containing files (in the VC directory), but point to the Windows CE containing files (in the WCE directory). Don't modify it.
Since the Windows CE is running under Windows NT, the program running on the emulator can call the function in any Windows NT Dynamic Link Library (DLL), even if this DLL is not a member of the simulator. Obviously, this is not a good thing, because the same function may not be available on the handheld PC (H / PC) or Windows CE device, and your software is ultimately running on these devices.
When you load a non-Unicode application into the Windows CE emulator, you will find that many functions that are being used are not supported, such as the Character Functions defined by the National Standards Association (ANSI). This may encourage you to link the Windows NT running time library so that you can solve all the problems. If you are programming with Windows CE, you can use the file and library files that you can use. The answer is that you don't use those containing files and library files used when writing a normal WIN32 or non-Windows CE program.
2. Don't confuse Tchars and Bytes
If you are writing non-Unicode applications on Windows CE, you might want to convert all strings from a single character (CHARS) (for example, C variable type WHCAR_T). Almost all WIN32 and runtime library functions supported by Windows CEs require wide character variables. Windows 95 does not support Unicode, however, in order to make the program code have portability, you must use the TCHAR type defined in tchar.h as much as possible, do not use WCHAR_T directly.
TCHAR is defined as WCHAR_T or CHAR, depending on whether the symbol Unicode of the preprocessor is defined. Similarly, all macros related to string processing functions, such as _tcsncpy macros, which are defined as Unicode functions WCSNCPY or defined as an ANSI function Strncpy, depending on whether Unicode is defined.
In existing Windows applications, some code may hint the character length is single byte. This is often used when allocating memory giving string, for example:
INT myfunc (char * p) {char * pszfilename;
PSZFilename = malloc (MaxFilelen); if (PSZFileName) Strncpy (PSZFilename, P, MaxFilelen); / * etc * /
In this code, the allocated memory block should be written (MAXFILEN * SIZEOF (CHAR), but most of the programmers like to simplify it to maxfilelen, because for all platforms, the value of SIZEOF (Char) is equal to 1. However, when you replace multiple characters with TChars, it is easy to forget this inherent concept, so write the code into the following form:
INT myfunc (tchar * p) {tchar * pszfilename;
PSZFileName = (Tchar *) Malloc (pszfilename) TCSNCPY (PSZFileName, P, MaxFilelen); / * etc * /
This is not. It will lead to an error. The error here is that the specified variable size in the malloc function is BYTES, but the third variable used in the _tcsncpy function is specified as TCHARS instead of bytes. When Unicode is defined, a TCHAR is equal to two bytes (bytes).
The above code segment should be rewritten as:
INT myfunc (tchar * p) {tchar * pszfilename;
PSZFileName = (Tchar *) Malloc (Maxfilelen * Sizeof (Tchar)); if (pszfilename) TCSNCPY (PSZFileName, P, MaxFilelen); / * etc * /
3. Do not put the Unicode string into an odd memory address
On the Intel Series processor, you can store any variables or arrays in a monarch memory address, and will not cause any fatal errors. But in the h / PC, this is not necessarily possible? You must be cautious about the type of data greater than one byte, including Wchar_T defined as unsigned shorts. When you try to access them, placing them in an odd address will result in overflow. The editor often reminds you on these issues. You can't manage the stack variable address, and the editor will check to determine if these addresses match if these addresses are matched. Similarly, the running time library must ensure that the memory allocated from the stack always satisfies a Word boundary, so you don't have to worry about it. However, if the application contains the code to copy memory area with the memcpy () function, or use some type of pointer arithmetic to determine the memory address, the problem may appear. Consider the following example:
INT sent_name (tchar * pszname) {char * p, * q; int Nlen = (_ tcslen (pszname) 1) * sizeof (tchar);
P = maloc (Header_size Nlen); if (p) {q = p header_size; _tcscpy ((tchar *) q, pszname);} / * etc * /
This code is allocated from the heap and copy a string, and leaves a header_size size in the beginning of the string. Suppose UNICODE is defined, then the string is a WideChar string. If header_size is an even number, this code will work normally, but if header_size is odd, this code will be wrong because Q Points will be odd.
Note that this problem does not occur when you test this code on the Windows CE emulator in the Intel Series processor.
In this example, just make sure the header_size is an even number, you can avoid problems. However, in some cases you may not do this. For example, if the program is input from a PC, you may have to use the prior defined binary format, although it is not suitable for H / PC. In this case, you must use a function that controls the string instead of the TCHAR pointer with a character pointer. If you know the length of the string, you can replicate the string with a memcpy (). Therefore, the function of using a Byte Analysis Unicode string may be sufficient to determine the length of the string in WideChars.
4. Translate between ANSI and Unicode strings
If your Windows CE application interface is on the desktop PC, you may have an ANSI string data (for example, a char string) in the PC. This is the fact even if you use the Unicode string in the program.
You can't handle an ANSI string on Windows CE because you don't manipulate their library functions. The best solution is to convert the ANSI string into a Unicode string to use the H / PC, and then convert the Unicode string back to the ANSI string to use the PC. In order to complete these conversions, multibyToWideChar () and widechartomultibyte () Win32 API functions can be used.
5. For Windows CE 1.0 string conversion, cleavage (HACK)
These Win32API functions have not been completed in Windows CE 1.0 versions. So if you want to support CE 1.0 and support CE 2.0, you must use other functions. Convert ANSI string to Unicode strings to use WSPrintf (), where the first parameter uses a WideChar string and knows "% s" (capital) means a string. Since there is no WSSCANF () and WSPrintfa (), you must think of a UNICODE string back into an ANSI string. Since Windows CE 1.0 is not in Country Language Support (NLS), you may have to help Hack, as shown below: / * Definition / prototypes of conversMulti-byte (ANSI) to widechar (unicode)
Atow () Converts from Ansi to Widecharwtoa () Converts from widechar to Ansi * / # = (_win32_wce> = 101)
#define atow (str, strw, lenw) / multibytetowidechar (CP_ACP, 0, Stra, -1, Strw, LENW)
#define WTOA (STRW, Stra, Lena) / Widechartomutibyte (CP_ACP, 0, STRW, -1, Stra, Lena, Null, NULL)
#ELSE / * _WIN32_WCE> = 101) * /
/ * MultibyToWideChar () NOT Supported O-N Windows CE 1.0 * / int Atow (CHAR * Stra, Wchar_T * STRW, INT LENW); int WTOA (Wchar_T * STRW, Char * Stra, Int Lena);
Endif / * _win32_wce> = 101 * /
#if (_WIN32_WCE <101)
INT ATOW (CHAR * STRA, WCHAR_T * STRW, INT LENW) {INT LEN; Char * Pa; Wchar_T * PW;
/ * START with LEN = 1, Not Len = 0, AS String Length Returnedmust Include Null Terminator, AS IN MultibyToWideChar () * / for (PA = Stra, PW = Strw, Len = 1; LENW; PA , PW , LENW- -, LEN ) {* pw = (lenw = = 1)? 0: (wchar_t) (* pa); if (! (* pw)) Break;} returnon;
int wtoa (wxhar_t * strW, char * strA, int lenA) {int len; char * pA; wchar_t * pW; / * Start with len = 1, not len = 0, as string length returnedMust include null terminator, as in WideCharToMultiByte () * / for (PA = Stra, PW = STRW, LEN = 1; LENA; PA , PW , Lena--, LEN ) {PA = (LEN == 1)? 0: (char) (pw); if (! (* pa)) Break;} return.
#ENDIF / * _WIN32_WCE <101 * / This implementation of this implementation of Windows CE 1.0 is easier than using the WSPrintf () function, because using the WSPrintf () function is more difficult to limit the length of the string pointed to by the target pointer.
6. Select the correct string comparison function
If you want to classify the Unicode standard string, you will have the following functions to choose from:
WCSCMP (), WCSNCMP (), WCSICMP (), and WCSNICMP ()
Wcscoll (), WCSNCOLL (), WCSicoll (), and WCSNICOLL ()
CompareString ()
The first class function can be used to compare the string, not refer to the local (LOCALE) or a foreign character. If you never want to support the foreign language, or you just want to test whether the contents of the two strings are the same, this type of function is very easy.
The second class function uses the current local settings (system settings, unless you call the WSETLOCALE () function before the string comparison function is before comparing two strings. These functions can also be classified correctly. If the local characters "C" ("C" locale) is selected, these functions have the same function as the first class function.
The third type of function is the Win32 function CompareString (). This function is similar to the second type of function, but it allows you to specify the locale as a parameter instead of using the current local settings. The CompareString () function allows you to selectively specify the length of the two strings. You can set the second parameter to Norm_ignoreCase to make the function compare the string when it is more written.
Typically, even if the second parameter is not set to norm_ignoreCase, the CompareString () function is not used to case sensitive. We often use wcsncoll () functions to case sensitive unless you use local characters "C" ("C" locale). So, in our code, don't use the CompareString () function to case sensitive, and use the wcsncoll () function to case sensitive
7. Don't use a relative path
Unlike Windows NT, Windows CE does not have the current directory, so any path is just relative to the root directory. If your software uses a relative path to the file or directory, you are likely to move them elsewhere. For example, the path "./ABC" is treated as "/ ABC" in Windows CE.
8. Remove calls to calloc () and time () functions
The Calloc () function in the C run can not be used, but the malloc () function can replace the Calloc () function. And don't forget, the memory allocated when the calloc () function is initialized, and the malloc () function is different. Similarly, the Time () function cannot be used, but you can use the Win32 function getSystemTime () function instead of the TIME () function.
After the above warning, you will be happy to learn the two advice of the ultimate you surprised.
9. Do not need to change the call of Win32 input / output (I / O) file
Win32 input and output functions, Windows CE also supports. Allow you to access the object as you visiting the Win32 file system. CreateFile () function does not claim flag file_flag_random_access in Windows CE, but this flag is used only as an optional disk access and does not affect the function called.
10. Don't worry about the state of bytes When we write the application to Windows CE, there is a good discovery, which is the byte state of the digital data type of Windows CE, like the byte state of the Intel structure, in all On the processor, Windows CE supports.
Like all database engines, the RAIMA Database Manager saves digital data in binary form in a database file. This means that a record is handled by a series of bytes whenever a series of bytes is written from the database or from the database, regardless of the content of its domain. As long as the database files do not pass any system, the byte status of digital data is solved. If the database file is accessed by a processor from the original system and with a different byte state, digital data will be misunderstood.
Whenever you transfer files when you have a file with different processors, you will have this problem. On this issue, it is worthy of all types of processors use the same byte state.
When using Windows CE, this 10 points should cause you to pay enough attention to avoid learning when learning.