📜 ⬆️ ⬇️

Programming under Windows CE in C ++ using Embedded Visual C ++, Part 3 (probably the last).

Programming under Windows CE in C ++ using Embedded Visual C ++, Part 3 (probably the last).

Continuation of the 1st and 2nd parts.


Now we will discuss in detail the differences between smartphones and Pocket PC. Ready? So: in PocketPC, you can poke a finger, but you cannot in a Smartphone. That's all!
')
The big problem with PDAs is that they don't have much memory. It would be nice to understand where we started and what is there. This can be done like this:

MEMORYSTATUS ms;
ZeroMemory(&ms, sizeof(ms));
ms.dwLength = sizeof(MEMORYSTATUS);
GlobalMemoryStatus(&ms);

ULARGE_INTEGER free = {0}, avail = {0}, total = {0};
GetDiskFreeSpaceEx(0, &free, &avail, &total);

// PocketPC
TCHAR platform[1000] = {0};
SystemParametersInfo(SPI_GETPLATFORMTYPE, 1000, platform, 0);

TCHAR OEM[1000] = {0};
SystemParametersInfo(SPI_GETOEMINFO, 1000, OEM, 0);

printf (_T(": %s."), OEM);
printf (_T(": %s."), platform);
printf (_T(", %d %d ."), ms.dwAvailVirtual >> 20, ms.dwTotalVirtual >> 20);
printf (_T(", %d ."), free.QuadPart >> 20);


Sometimes on the PDA, you can rotate the screen in landscape and portrait orientation. Here are the necessary functions:

// ?
bool CanRotateScreen()
{
#ifdef UNDER_CE
DEVMODE dm;
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(DEVMODE);
dm.dmFields = DM_DISPLAYQUERYORIENTATION;
return DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettingsEx(NULL, &dm, NULL, CDS_TEST, NULL);
#else
return false;
#endif
}

// ?
int ScreenRotationAngle()
{
#ifdef UNDER_CE
DEVMODE dm;
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(DEVMODE);
dm.dmFields = DM_DISPLAYORIENTATION;
ChangeDisplaySettingsEx(NULL, &dm, NULL, CDS_TEST, NULL);
switch (dm.dmDisplayOrientation)
{
case DMDO_0: return 0;
case DMDO_90: return 90;
case DMDO_180: return 180;
case DMDO_270: return 270;
}
#endif
return -1;
}

// !
void RotateScreen(int angle)
{
#ifdef UNDER_CE
DEVMODE dm;
memset(&dm, 0, sizeof(dm));
dm.dmSize = sizeof(DEVMODE);
dm.dmFields = DM_DISPLAYORIENTATION;
switch (angle)
{
default:
case 0: dm.dmDisplayOrientation = DMDO_0;
case 90: dm.dmDisplayOrientation = DMDO_90;
case 180: dm.dmDisplayOrientation = DMDO_180;
case 270: dm.dmDisplayOrientation = DMDO_270;
}
ChangeDisplaySettingsEx(NULL, &dm, NULL, CDS_RESET, NULL);
#endif

}


Do not forget to respond to the WM_SETTINGCHANGE message! You may want to understand what the screen now looks like:

...
Screen.right = GetSystemMetrics(SM_CXSCREEN) - 1;
Screen.bottom = GetSystemMetrics(SM_CYSCREEN) - 1;
...


Since it is impossible to grasp the immensity, I’m getting round here, but I’ll tell you at the end how to install your application under the PDA. You want to create a normal human installer from under Win32, and not default squalor, right?

You need RAPI.DLL. If you search the network, you can find RAPI.H, which describes an incredible number of structures and functions in RAPI.DLL, some of which you need. Using RAPI.DLL, you can establish whether the PDA is connected to a desktop PC, rummage through its files, copy files from the desktop to the PDA and back, create shortcuts, etc.

This is done approximately like this (Delphi code, do not worry!):

type

TRapiInit = record
cbSize:DWORD;
heRapiInit:THandle;
hrRapiInit:HResult;
end;

function CeCloseHandle(hObject: THandle): bool; stdcall external 'rapi.dll';
function CeCreateFile(lpFileName: LPCWSTR; dwDesiredAccess: dword; dwShareMode: dword; lpSecurityAttributes: PSecurityAttributes; dwCreationDistribution: dword; dwFlagsAndAttributes: dword; hTemplateFile: THandle): THandle; stdcall external 'rapi.dll';
function CeGetFileSize(hFile: THandle; lpFileSizeHigh: PDWORD): dword; stdcall external 'rapi.dll';
function CeGetLastError: dword; stdcall external 'rapi.dll';
function CeRapiInitEx(var RapiInit: TRapiInit): longint; stdcall external 'rapi.dll';
function CeRapiUninit: longint; external 'rapi.dll';
function CeReadFile(hFile: THandle; const lpBuffer; nNumberOfBytesToRead: dword; var NumberOfBytesRead :dword; Overlapped: POVERLAPPED): bool; stdcall external 'rapi.dll';
function CeWriteFile(hFile: THandle; const lpBuffer; NumberOfBytesToWrite: dword; var NumberOfBytesWritten :dword; Overlapped: POVERLAPPED): bool; stdcall external 'rapi.dll';
function CeCreateDirectory(lpPathName:LPCWSTR; lpSecurityAttributes:PSecurityAttributes):BOOL; stdcall external 'rapi.dll';
function CeRemoveDirectory(PathName:LPCWSTR):BOOL; stdcall external 'rapi.dll';
function GetRapiError: integer; stdcall external 'rapi.dll';

procedure InitRAPI(wait_ms: cardinal);
var
ri: TRapiInit;
h: HRESULT;
when: cardinal;
begin
ZeroMemory(@ri, sizeof(ri));
ri.cbSize := sizeof(ri);
h := CeRapiInitEx(ri);
if FAILED(h) then raise Exception.Create(' .');
when := GetTickCount + wait_ms;
while GetTickCount < when do
case MsgWaitForMultipleObjects(1, ri.heRapiInit, FALSE, when - GetTickCount,QS_ALLINPUT) of
WAIT_OBJECT_0: if SUCCEEDED(ri.hrRapiInit) then exit else raise Exception.Create(' PDA.');
WAIT_OBJECT_0 + 1: Application.ProcessMessages;
end;
raise Exception.Create(' .');
end;

procedure CopyFileToPDA(src_filename, dst_filename: string; ignore_errors: boolean );
var
buffer: array [0..16384] of char;
BufferCount, ReadCount, WriteCount: cardinal;
dst, src: THandle;
filename: pWideChar;
code: longbool;
begin
GetMem(filename, sizeof(WideChar) * Succ(Length(dst_filename)));
StringToWideChar(dst_filename, filename, Succ(Length(dst_filename)));
try
src := CreateFile(PChar(src_filename), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if GetLastError = INVALID_HANDLE_VALUE then raise Exception.CreateFmt(' "%s".', [src_filename]);
dst := CeCreateFile(filename, GENERIC_READ or GENERIC_WRITE,0,nil,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
if (CeGetLastError = INVALID_HANDLE_VALUE) then raise Exception.CreateFmt(' "%s" .', [dst_filename]);
BufferCount := 16384; ReadCount := 16384;
while ReadFile(src,Buffer,BufferCount,ReadCount,nil) and (ReadCount <> 0) do begin
code := CeWriteFile(dst,buffer,ReadCount,WriteCount, nil);
if not code and not ignore_errors then
raise Exception.Create(' "' + src_filename + '" ("' + dst_filename + '").');
Application.ProcessMessages;
end;
CloseHandle(src);
CeCloseHandle(dst);
finally
FreeMem(filename);
end;
end;



Maybe you want to write the application directly to the memory card? Then try to find it like this:

function StorageCardPath: string;
var
h: THandle;
data: CE_FIND_DATA;
name: string;
const
a = FILE_ATTRIBUTE_TEMPORARY or FILE_ATTRIBUTE_DIRECTORY;
begin
h := CeFindFirstFile('\*.*', @data);
while h <> INVALID_HANDLE_VALUE do begin
if (data.dwFileAttributes and a) = a then begin
name := WideCharToString(data.cFileName);
if Pos('NETWORK', UpperCase(name)) = 0 then begin
result := '\' + name;
break;
end;
end;
if not CeFindNextFile(h, @data) then break;
end;
CeFindClose(h);

end;


In general, I advise you to study the RAPI, there are a lot of useful things there. The most important thing is that you have a human installer and full control over the installation process.

Good luck!

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


All Articles