Click here to Skip to main content
15,897,518 members
Articles / Programming Languages / Objective C

Running State Machine Based Win32/WinCE Programs

Rate me:
Please Sign up or sign in to vote.
4.37/5 (9 votes)
17 May 20065 min read 71K   1.3K   35  
This article describes how to run state machine application framework based Win32/WinCE programs using the window message hooking technology. (Open source project)
//Main.c
#include "../GHdr/sme_debug.h"
#include "stdlib.h"
#include "Service.h"
#include "SrvAgent.h"
#include "main.h"

SME_DEC_EXT_APP_VAR(PowerUpDown);
SME_DEC_EXT_APP_VAR(MediaPlay);

int OnEventComeHook(SME_EVENT_ORIGIN_T nEventOrigin, struct SME_EVENT_T *pEvent);
int OnMemOprHook(SME_MEM_OPR_HOOK_TYPE_T nAllocType, void *pUserData, unsigned int nSize, 
				 const char *sFileName, int nLineNumber);

BOOL AttachPortToApp(SME_APP_T *pApp, void **pPortInfo);
SME_APP_T * GetApp(void* pPortInfo);

unsigned int g_nUserMemSize=0;

SME_THREAD_CONTEXT_PT g_pAppChildThreadContext;
/******************************************************************************************
 DESCRIPTION:  The main entry of application.
 INPUT:  None.
 OUTPUT: 
 NOTE: 
*******************************************************************************************/
void AppMain(SME_THREAD_CONTEXT_PT pAppThreadContext)
{
	SmeInitEngine(pAppThreadContext); // Initialize engine
	
	AttachPortToApp(&SME_GET_APP_VAR(PowerUpDown),SrvGetPortInfoPtr());
	AttachPortToApp(&SME_GET_APP_VAR(ImageList),SrvGetPortInfoPtr());
	AttachPortToApp(&SME_GET_APP_VAR(MenuCtrl),SrvGetPortInfoPtr());
	AttachPortToApp(&SME_GET_APP_VAR(DialogCtrl),SrvGetPortInfoPtr());
	AttachPortToApp(&SME_GET_APP_VAR(EditCtrl),SrvGetPortInfoPtr());

	SmeSetOnEventComeHook(OnEventComeHook);
	SME_SET_MEM_OPR_HOOK(OnMemOprHook);

	SmeActivateApp(&SME_GET_APP_VAR(PowerUpDown),NULL);

	// By default, all module trancers are turned on. Turn off MODULE_SRV_CALL_DISP tracer.
	SME_TURN_OFF_MODULE_TRACER(MODULE_SRV_CALL_DISP);

	SmeRun();
}

/******************************************************************************************
 DESCRIPTION:  The entry function of the child thread: MediaPlay.
 INPUT:  None.
 OUTPUT: 
 NOTE: 
*******************************************************************************************/
void AppChildThread(SME_THREAD_CONTEXT_PT pThreadContext)
{
	SmeInitEngine(pThreadContext); // Initialize engine for the child thread.
	g_pAppChildThreadContext = pThreadContext;
	
	SmeActivateApp(&SME_GET_APP_VAR(MediaPlay),NULL);
	SmeRun();
}

/******************************************************************************************
 DESCRIPTION:  Event arrival hook function.
 INPUT:  
	 nEventOrigin: Event origin, internal or external;
	 pEvent: Incoming event pointer.
 OUTPUT: 
 NOTE: This hook function will translate external key press event into UI events:
		EVENT_KEY_POWER, EVENT_KEY_OK,EVENT_KEY_CANCEL,EVENT_KEY_LEFT,EVENT_KEY_RIGHT ...
*******************************************************************************************/
int OnEventComeHook(SME_EVENT_ORIGIN_T nEventOrigin, struct SME_EVENT_T *pEvent)
{
	MSG_KEY_PRESS_T *pKeyPressData;
	SME_EVENT_ID_T nEventId = EVENT_KEY_0;
	SME_EVENT_T *pKeyEvent;

	if (nEventOrigin == SME_EVENT_ORIGIN_EXTERNAL)
	{
		/* When receives a keypad event, create a UI event. They will be sent to focused application only.*/
		if (pEvent->nEventID == EXT_EVENT_ID_KEY_PRESS)
		{
			pKeyPressData = (MSG_KEY_PRESS_T *)(pEvent->Data.Ptr.pData);		
			switch (pKeyPressData->nKeyCode)
			{
			case KEY_CODE_RIGHTSOFT:
				nEventId = EVENT_KEY_RIGHTSOFT;
				break;
			case KEY_CODE_LEFTSOFT:
				nEventId = EVENT_KEY_LEFTSOFT;
				break;
			case KEY_CODE_POWER:
				nEventId = EVENT_KEY_POWER;
				pKeyEvent = SmeCreateIntEvent(nEventId,0,0,SME_EVENT_CAT_OTHER,NULL);
				SmePostEvent(pKeyEvent);
				return TRUE;
			case KEY_CODE_UP:
				nEventId = EVENT_KEY_UP;
				break;
			case KEY_CODE_DOWN:
				nEventId = EVENT_KEY_DOWN;
				break;
			case KEY_CODE_0:
			case KEY_CODE_1:
			case KEY_CODE_2:
			case KEY_CODE_3:
			case KEY_CODE_4:
			case KEY_CODE_5:
			case KEY_CODE_6:
			case KEY_CODE_7:
			case KEY_CODE_8:
			case KEY_CODE_9:
				nEventId = EVENT_KEY_0 + (pKeyPressData->nKeyCode - KEY_CODE_0); 
				break;
			};
			pKeyEvent = SmeCreateIntEvent(nEventId,0,0,SME_EVENT_CAT_UI,NULL);
			SmePostEvent(pKeyEvent);
		}
		/* When receives an event with a destination port. Map the port to the appropriate application.*/
		if (pEvent->pPortInfo != NULL)
			pEvent->pDestApp=GetApp(pEvent->pPortInfo);
	}
	return TRUE;
}

int OnMemOprHook (SME_MEM_OPR_HOOK_TYPE_T nAllocType, void *pUserData, unsigned int nSize, const char *sFileName, int nLineNumber) {
	
	static int g_nUserMemSize=0;
	static SME_EVENT_ID_T nEventId;
	const int nMemoryLimit=100;
	SME_EVENT_T *pInteralEvent;

	if (nAllocType==SME_HOOK_PRE_ALLOC && (g_nUserMemSize+(int)nSize)>nMemoryLimit)
	{
		nEventId=EVENT_OUT_OF_MEMORY;
		pInteralEvent = SmeCreateIntEvent(nEventId,0,0,SME_EVENT_CAT_OTHER,NULL);
		SmePostEvent(pInteralEvent);
		return FALSE;
	}

	if(nAllocType==SME_HOOK_POST_ALLOC)
		g_nUserMemSize+=nSize;
	else if(nAllocType==SME_HOOK_POST_FREE)
		g_nUserMemSize-=nSize;
	SrvUpdateMemoryStatistic(g_nUserMemSize);
	return TRUE;
}

/********************** Port and application mapping *************************************/

BOOL AttachPortToApp(SME_APP_T *pApp, void **pPortInfo)
{
	if (pApp==NULL || pPortInfo==NULL) return FALSE;

	*(SME_APP_T **)(pPortInfo) = pApp;
	pApp->pPortInfo = *pPortInfo;

	return TRUE;
}

SME_APP_T * GetApp(void* pPortInfo)
{
	if (pPortInfo==NULL) return NULL;

	return (SME_APP_T *)(pPortInfo);
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


Written By
Web Developer
China China
Jerome. (Free to speak, free to use.)

Comments and Discussions