📜 ⬆️ ⬇️

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 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 code for Windows CE only
#else
// code for Windows 32 only
#endif


WinMain is a little 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 you 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 absence of a discontinuous line of type composed of points on Win CE:

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

Under Win CE, we don’t have the current cursor position, so you understand. 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

At the same time, keep these functions:

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 is how the beginning of the h-file looks like for me, which is included in each compiled file first:

#pragma warning (disable: 4786)
#pragma once

#ifndef UNICODE
#error You must define UNICODE
#endif

#ifndef _UNICODE
#error You must 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 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.

Source: https://habr.com/ru/post/39938/


All Articles