Programming under Windows CE using Embedded Visual C ++, Part 1

    This post is for real programmers who, instead of the primer, taught the alphabet on the third edition of the C ++ handbook. We will program in Windows CE in C ++ using Embedded Visual C ++.

    So, we will need:


    1. eMbedded Visual C ++ 4.0 (TRT7H-KD36T-FRH8D-6QH8P-VFJHQ)
    2. eMbedded Visual C ++ 4.0 service pack 4
    3. ritti.exe
    4. Microsoft Pocket PC 2003 SDK.msi
    5. Microsoft ActiveSync
    6. StandAlone Emulator

    This Kit allows you to develop programs that run on all Windows Mobile since 2003. Forget about innovations in Windows Mobile 5 and 6 (unless you don't need them :). All of these products are through Google, but install them a little bit. Emulator is especially annoying, which requires the installation of the following things in the following order:

    1. netsvwrap.msi
    2. standalone_emulator_V1.exe
    3. efp.msi
    4. emulator_2_0.msi

    If you are still here - continue!

    Briefly, the differences between the WinCE API and the Win32 API are as follows: only Unicode, the absence of the current directory (only absolute paths), cumbersome things are trimmed, the presence of features with input.

    I created a cross-platform product (under WinCE and Win32). This is how it is done in a nutshell. Using UNDER_CE to distinguish the platform:

    #ifdef UNDER_CE
    // here is the code for Windows CE
    only #else
    // here is the code for Windows 32 only
    #endif


    WinMain is slightly different:

    #ifdef UNDER_CE
    int WINAPI WinMain (HINSTANCE h, HINSTANCE prev, LPTSTR line , int cmd)
    #else
    int WINAPI WinMain (HINSTANCE h, HINSTANCE prev, LPSTR line, int cmd)
    #endif

    The easiest thing to do is both UNICODE projects. This will simplify the code. In STL, there is a wonderful wstring class for working with a UNICODE string. String literals should look like this:

    _T (“Goodbye, world!”)

    _T () is a macro that will turn a string literal into UNICODE or ASCII as needed. Instead of char we use TCHAR .

    To make a UNICODE project in Win32, set two preprocessor definitions: _UNICODE and UNICODE. In Embedded C ++ this will be done by default.

    Since there is no current directory, all paths are absolute and you have to take care of adding the necessary prefix yourself. This is how we find where we were launched from:

    wstring ApplicationPath ()
    {
    TCHAR Path [MAX_PATH + 1] = {0};
    int n = GetModuleFileName (0, Path, MAX_PATH);
    while (--n> 0 && Path [n]! = _T ('\\') && Path [n]! = _T ('/'))
    Path [n] = 0;
    return path;
    }

    This is how we pervert if we need something only under Windows 32:

    typedef DWORD (WINAPI * FUNC_GetGuiResources) (HANDLE, DWORD);
    FUNC_GetGuiResources f_GetGuiResources = 0;

    struct Win2000_Linkage {Win2000_Linkage () {
    #ifndef UNDER_CE
    f_GetGuiResources = (FUNC_GetGuiResources) GetProcAddress (GetModuleHandle (_T ("user32.dll")), "GetGuiResources");
    #endif
    }} Win2000_linkage;

    int GetGuiResource (DWORD which)
    {
    #ifndef UNDER_CE
    if (f_GetGuiResources == 0) return 0;
    HANDLE h = OpenProcess (PROCESS_QUERY_INFORMATION, false, GetCurrentProcessId ());
    int n = f_GetGuiResources (h, which);
    CloseHandle (h);
    return n;
    #else
    return 0;
    #endif
    }

    Here is another strange piece of code that apparently appeared due to the lack of a discontinuous type line made up of dots on Win CE:

    #ifdef UNDER_CE
    #define DASH_STYLE PS_DASH
    #else
    #define DASH_STYLE PS_DOT
    #endif

    We don’t have any CE Under Win CE The current position of the cursor, because you know. Therefore, if it is needed, then remember the last event from the mouse and consider this position as the cursor position. Type:

    #ifdef UNDER_CE
    POINT mouse = mouse_at;
    #else
    POINT mouse = WhereIsCursor ();
    #endif

    Under Win CE, there is no Arc () primitive (see GDI).

    But! But under Win CE there is still something good. This is good - Chro ... is built into the OS, that is, Oper .., that is, Inernet Explorer! Fuu, I remembered the name of the same! Of course, he is a little bit simpler than his older brother, but we don’t need much - just draw nice HTML text and that's it!

    First we do:

    BOOL InitHTMLControl (
    HINSTANCE hinst);

    You can add a control with a WC_HTML class to the window.
    And send some HTML into it to display:
    SendMessage (hwndHTML, WM_SETTEXT, 0, (LPARAM) "");
    SendMessage (hwndHTML, DTM_ADDTEXTW, FALSE, (LPARAM) TEXT ("Hello"));
    SendMessage (hwndHTML, DTM_ADDTEXTW, FALSE, (LPARAM) TEXT ("World!"));
    SendMessage (hwndHTML, DTM_ENDOFSOURCE, 0, (LPARAM) NULL);

    Under Win 32, richedit controls can be used for similar purposes.

    Under Win CE, there is no GetPrivateProfileString, so reading and parsing INI files is your prerogative.

    When loading a DLL under Win32, the function name must be in ANSI. Although the project and under UNICODE. Why? Because!

    #ifndef UNDER_CE
    string f_name = ANSI (func_name);
    FARPROC f = GetProcAddress (h, f_name.data ());
    #else
    FARPROC f = GetProcAddress (h, func_name);
    #endif

    Hold these functions at the same time:

    string ANSI (wstring w)
    {
    int l = WideCharToMultiByte(CP_ACP, 0, w.data(), w.size(), NULL, 0, NULL, NULL);
    if (l)
    {
    char* buffer = new char[l + 1];
    l = WideCharToMultiByte(CP_ACP, 0, w.data(), w.size(), buffer, l, NULL, NULL);
    buffer[l] = 0;
    string s(buffer);
    delete[] buffer;
    return s;
    }
    return "";
    }

    wstring UniCODE(string w)
    {
    int l = MultiByteToWideChar(CP_ACP, 0, w.data(), w.size(), NULL, 0);
    if (l)
    {
    TCHAR* buffer = new TCHAR[l + 1];
    l = MultiByteToWideChar(CP_ACP, 0, w.data(), w.size(), buffer, l);
    buffer[l] = 0;
    wstring s(buffer);
    delete[] buffer;
    return s;
    }
    return _T ("");
    }

    Here's how I look at the beginning of h-file, which is included in each compiled file first:

    #pragma warning (the disable: 4786)
    #pragma once recording

    #ifndef the UNICODE
    #error You a must the define the UNICODE
    #endif

    #ifndef _UNICODE
    #error You a must the define _UNICODE
    #endif

    #ifndef WINVER
    #define _WIN32_WINNT 0x0400
    #define WINVER 0x0400
    #endif

    #ifndef UNDER_CE
    #include <tchar.h>
    #include <crtdbg.h>
    #define ASSERT (expr) _ASSERT (expr)
    #define IDC_HAND the MAKEINTRESOURCE (32649)
    # define GR_GDIOBJECTS 0 / * Count of GDI objects * /
    #define GR_USEROBJECTS 1 / * Count of USER objects * /
    #define WS_NONAVDONEBUTTON 0
    #include <math.h>
    #endif
    #include "windows.h"
    #include #include #include #include #include #include using namespace std;

    As you can see, I use STL closely and therefore I load its classes into the default namespace.

    So far, if I liked everything in the next part, I’ll tell you about the pop-up keyboard (SIP), determining the screen orientation and its rotation, adjusting to the screen size, determining the DPI and adjusting it, magic passes to appear in the upper right corner of the cross covering the application (and not it is unknown where), the emergence of reminders, etc.


    Also popular now: