📜 ⬆️ ⬇️

Programming under Windows CE in C ++ using Embedded Visual C ++, Part 2.

Programming under Windows CE in C ++ using Embedded Visual C ++, Part 2.

Continuation of the 1st part .


Under Win CE there is an analogue of InitCommonControls () and it is called SHInitExtraControls (). It is best to call this function once when the application starts, so that any additional controls work in your application.
')
The pop-up keyboard on the PDA is called SIP (advanced Stupid Input Panel). This is a rectangle that takes away some of the visible screen. Understand how much is left so (do not forget to include aygshell.h and link aygshell.lib):

Sipinfo si;
memset (& si, 0, sizeof (si));
si.cbSize = sizeof (si);
SHSipInfo (SPI_GETSIPINFO, 0, (PVOID) & si, FALSE);
bool SIP_visible = si.fdwFlags & SIPF_ON;
if (! SIP_visible) si.rcVisibleDesktop.bottom = si.rcSipRect.bottom;
return si.rcVisibleDesktop;


You can hide and show SIP yourself (for example, when the edit control receives focus, it is reasonable to show SIP for data entry):

void CloseSIP ()
{
#ifdef UNDER_CE
SHSipPreference (MainForm () -> hwnd, SIP_DOWN);
#endif
}

void OpenSIP ()
{
#ifdef UNDER_CE
SHSipPreference (MainForm () -> hwnd, SIP_UP);
#endif
}


Here is another interesting piece of code that helps SIP keep its state when our windows get WM_ACTIVATE:

case WM_ACTIVATE:
if (wp! = WA_INACTIVE) {
#ifdef UNDER_CE
if (control == ActiveForm () && control-> FullScreen)
SHHandleWMActivate (control-> hwnd, wp, lp, & sai, 0);
#endif
...


When something changes in the system, it sends a WM_SETTINGCHANGE message:

case WM_SETTINGCHANGE:
#ifdef UNDER_CE
if (MainForm ())
SHHandleWMSettingChange (MainForm () -> hwnd, wp, lp, & sai);
if (wp == SETTINGCHANGE_RESET)
Application-> GetScreen ();
#endif
break;


There are many things on the Windows Mobile platform that idiot ... sorry, weird ideas. In my personal parade hit the first place on idiocy takes a button in the upper right corner. The default behavior of this button is this: it does not close the application (although a cross is drawn there), but removes it from the foreground. And the user doesn’t have a decent way to quickly find and open it except to go deep into the list of active processes or to search and launch this application again. All this supposedly should save time launching frequently used applications. The author of this idea can personally get a chocolate medal "For excellent idiocy"!

So, we will transform this stupid cross into a wonderful button with the inscription “OK” like this:

void AllowToCloseWindow (HWND hwnd)
{
#ifdef UNDER_CE
ModifyStyle (0, WS_CAPTION | WS_CHILD);
SetExStyle (WS_EX_CAPTIONOKBTN);
SHDoneButton (hwnd, SHDB_SHOW);
#else
ModifyStyle (WS_SYSMENU);
#endif
}


Of course, I was not the first to guess about the idiocy of the cross. There were craftsmen who release a package that turns Windows Mobile into an iPhone (joke). So sometimes they reprogram the behavior of the cross. Be prepared for this, the application can receive the WM_CLOSE message in the main window or something else when you click on the cross. Ask the developers what exactly!

The next rich topic is that the CCP has (mostly) two kinds of screens: 320x240 and 640x480. At the same time, they are of the same size. That is, they have a different DPI (number of dots per square inch). To work with 640x480, you must first explain to the system what you know. This is done by including the resource in the project:

HI_RES_AWARE CEUX DISCARDABLE
BEGIN
0x0001
END


If this is not done, then even on a PDA with 640x480 your application will run in a mode that simulates 320x240. Now, at startup, we need to understand whether we are dealing with a large screen:

bool HiRes ()
{
return GetSystemMetrics (SM_CXSCREEN)> = 640 || GetSystemMetrics (SM_CYSCREEN)> = 640;
}

However, this is not enough. We also need DPI to calculate:

double SCALE = 1.0;
bool HighDPI (int dpi = 130)
{
if (DPI == 0)
{
HDC hdc = GetDC (0);
int DPI = GetDeviceCaps (hdc, LOGPIXELSX);
bool result = DPI> = dpi;
ReleaseDC (0, hdc);
SCALE = DPI / 96.0;
return result;
}
Return DPI> = dpi;
}

And memorize in SCALE the scaling factor. And now you can use the following 2 functions:

int Descale (int a)
{
return int (a / SCALE);
}

int Scale (int a)
{
return int (a * SCALE);
}

Now, when drawing on the canvas, all coordinates are translated into actual using Scale (), and when receiving mouse messages, all coordinates are translated back using Descale ().

Continued to follow!

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


All Articles