emWin PC simulation
The PC simulation of emWin allows you to compile the same "C" source on your Windows PC using a native (typically Microsoft) compiler and create an executable for your own application. Doing so allows the following:
- Design of the user interface on your PC (no need for hardware!)
- Debugging of your user interface program.
- Creation of demos of your application, which can be used to discuss the user interface.
The resulting executable can be easily sent via email.

Using the simulation
The emWin simulation requires Microsoft Visual C++ (version 6.00 or higher) and the integrated development environment (IDE) which comes with it. You will see a simulation of your LCD on your PC screen, which has the same resolution in X and Y and can display the exact same colors as your LCD once it has been properly configured. The entire graphic library API and window manager API of the simulation are identical to those on your target system; all functions will behave in the very same way as on the target hardware since the simulation uses the same C source code as the target system. The difference lies only in the lower level of the software: the display driver. Instead of using the actual display driver, the PC simulation uses a simulation driver which writes into a bitmap. The bitmap is then displayed on your screen using a second thread of the simulation. This second thread is invisible to the application; it behaves just as if the LCD routines were writing directly to the display.
Using the simulation with the trial version of emWin
The trial version of emWin contains a full library which allows you to evaluate all available features of emWin. It also includes the emWin viewer (used for debugging applications), as well as demo versions of the font converter and the bitmap converter. Keep in mind that, being a trial version, you will not be able to view the source code of emWin or the simulation, but you will still be able to become familiar with what emWin can do.
Directory structure
The directory structure of the simulation in the trial version is shown at the right side. The table below explains the contents of the folders:
| ![]() |
Visual C++ workspace
| The root directory shown above includes the Microsoft Visual C++ workspace (SimulationTrial.dsw) and project file (SimulationTrial.dsp). The workspace allows you to modify an application program and debug it before compiling it on your target system. Double-click the workspace file to open the Microsoft IDE. The directory structure of the Visual C++ workspace will look like the one shown to the right. | ![]() |
Compiling the demo program
The source files for the demo program are located in the Application directory as a ready-to-go simulation, meaning that you only need to rebuild and start it. Note that to rebuild the executable, you will need to have Microsoft Visual C++ (version 6.00 or later) installed.
- Step 1: Open the Visual C++ workspace by double-clicking on SimulationTrial.dsw.
- Step 2: Rebuild the project by choosing Build/Rebuild All from the menu (or by pressing F7).
- Step 3: Start the simulation by choosing Build/Start Debug/Go from the menu (or by pressing F5).
The demo project will begin to run and may be closed at any time by right-clicking on it and selecting Exit.
Compiling the examples
The SampleExample directory contains ready-to-go examples that demonstrate different features of emWin and provide examples of some of their typical uses. In order to build any of these executables, their C source must be ’activated’ in the project. This is easily done with the following procedure:
- Step 1: Exclude the Application folder from the build process by right-clicking the Application folder of the workspace and selecting ’Settings\General\Exclude from build’.
- Step 2: Open the SampleExample folder of the workspace by double-clicking on it. Include the example which should be used by right-clicking on it and deselecting ’Settings\General\Exclude’ from build.
- Step 3: If the example contains its own configuration files (LCDConf.c and/or SIMConf.c) the default configuration files located in the config folder need to be excluded from the build process.
- Step 4: Rebuild the example by choosing Build/Rebuild All from the menu (or by pressing F7).
- Step 5: Start the simulation by choosing Build/Start Debug/Go from the menu (or by pressing F5). The result of the example selected above is pictured below:

Using the simulation with the emWin source
Directory structure
| The root directory of the simulation can be anywhere on your PC, for example C:\Work\emWinSim. The directory structure will appear as shown to the right. This structure is very similar to that which we recommend for your target application (see Chapter 3: "Getting Started" for more information). The following table shows the contents of the folders: | ![]() |
| Directory | Content |
|---|---|
| Doc | Contains emWin-Documentation. |
| Sample | Code examples, described later in this documentation. |
| Start | All you need to create a new project with emWin. |
| Tool | Tools shipped with emWin. |
| A new project can be started by making a copy of the Start-folder. It contains all required files for a new project. Subdirectories containing the emWin sources are in the Start\GUI folder and should contain the exact same files as the directories of the same names which are used for your target (cross) compiler. The files of the GUI subdirectories should not be changed, as this would make updating to a newer version of emWin more difficult. The Start\Config directory contains configuration files which need to be modified in order to reflect your target hardware settings (mainly LCD-size and colors which can be displayed). | ![]() |
Visual C++ workspace
| The root directory shown above includes the Microsoft Visual C++ workspace (Simulation.dsw) and project files (Simulation.dsp). The workspace allows you to modify an application program and debug it before compiling it on your target system. The directory structure of the Visual C++ workspace will appear similar to that shown to the right. Here, the GUI folder is open to display the emWin subdirectories. Note that your GUI directory may not look exactly like the one pictured, depending on which additional features of emWin you have. The folders Core, Font and DisplayDriver are part of the basic emWin package and will always appear in the workspace directory. | ![]() |
Compiling the application
The simulation contains one or more application C files (located in the Application directory), which can be modified or removed and additional files can be added to the project. You should then rebuild the program within the Visual C++ workspace in order to test/debug it. Once you have reached a point where you are satisfied with the result and want to use the program in your application, you should be able to compile these same files on your target system and get the same result on the target display. The general procedure for using the simulation would be as follows:
- Step 1: Open the Visual C++ workspace by double-clicking on Simulation.dsw.
- Step 2: Compile the project by choosing Build/Rebuild All from the menu (or by pressing F7).
- Step 3: Run the simulation by choosing Build/Start Debug/Go from the menu (or by pressing F5).
- Step 4: Replace the bitmap with your own logo or image.
- Step 5: Make further modifications to the application program as you wish, by editing the source code or adding/deleting files.
- Step 6: Compile and run the application program within Visual C++ to test the results. Continue to modify and debug as needed.
- Step 7: Compile and run the application program on your target system.
Advanced features of the simulation
Clicking the right mouse button shows a context menu with several advanced functions: Pause and ResumeThese menu items allows to pause and to resume the application currently running in the simulation. The same can be done by pressing <F4> or <F5>. Trying to pause an already paused application or trying to resume an already running application causes an error message. | ![]() |
View system info
| This menu item opens a further window with information of the memory currently used by the application. The window continuously shows the current status of memory consumption by showing the free and used bytes and the free and used number of memory blocks.
| ![]() |
Copy to clipboard
This menu item copies the current contents of the display into the clipboard. This makes it easy to use it for documentation purpose with other applications.
Device simulation
The device simulation supports 3 views:
- Generated frame view
- Custom bitmap view
- Window view
The table below shows the different views:
| Generated frame view | Custom bitmap view |
|---|---|
![]() | ![]() |
| Window view |
|---|
![]() |
The following will explain in detail how each option can be used.
Generated frame viewThe simulation shows the display inside an automatically generated frame surrounding the display. The frame contains a small button which per default closes the application. This is the default behavior of the simulation for single layer systems. ’Single layer system’ means that only the first layer is initialized. | ![]() |
Custom bitmap view
The simulation can show the simulated display in a bitmap of your choice, typically your target device. The bitmap can be used to simulate the behavior of the entire target device. In order to simulate the appearance of the device, bitmaps are required.
Device bitmapThe first bitmap is usually a photo (top view) of the device, and needs to be named Device.bmp. It may be a separate file (in the same directory as the executable), or it may be included as a resource in the application. How to do this is explained later in this chapter.The file should provide an area for the simulated display of the same size in pixels as the physical display resolution. If there are any hardkeys to be simulated the bitmap should also show all of them in unpressed state. Transparent areas need to be colored with exact the same color as defined with the function SIM_GUI_SetTransColor(), typically bright red (0xFF0000). These areas do not have to be rectangular; they can have an arbitrary shape (up to a certain complexity which is limited by your operating system, but is normally sufficient). Bright red is the default color for transparent areas, mainly because it is not usually contained in most bitmaps. To use a bitmap with bright red, the default transparency color may be changed with the function SIM_GUI_SetTransColor(). | ![]() |
Hardkey bitmapThe second bitmap file is required for defining the hardkeys and must be named Device1.bmp. It contains the buttons in pressed state. The non hardkey area has to be filled with the transparent color. This is only a short description. For more details about how to simulate hardkeys, see “Hardkey simulation” on page 54. | ![]() |
Using separate files
When starting the simulation, it checks if the directory of the executable contains the bitmap files Device.bmp and Device1.bmp. If these files are available, they are used automatically and the resource bitmaps are ignored. Note that this is only valid with single layer systems.
Adding the bitmap to the application resources
The resource file of the simulation can be found under System\Simulation\Res\Simulation.rc. It contains the following section:
///////////////////////////////////////////////////////////////////////////// // // Customizable bitmaps // IDB_DEVICE BITMAP DISCARDABLE "Device.bmp" IDB_DEVICE1 BITMAP DISCARDABLE "Device1.bmp"
This section can be used to set custom device files. For more information, refer to the Win32 documentation.
Window view
Default for simulating a multiple layer system is showing each layer in a separate window without using bitmaps or a generated frames.
Device simulation API
All of the device simulation API functions should be called in the setup phase. The calls should be done from within the routine SIM_X_Config(), which is located in the file SIMConf.c in the configuration folder. The example below calls SIM_SetLCDPos() in the setup:
#include "LCD_SIM.h"
void SIM_X_Config() {
SIM_GUI_SetLCDPos(50, 20); // Define the position of the LCD in the bitmap}
}
The table below lists the available device-simulation-related routines in alphabetical order:
| Routine | Explanation |
|---|---|
| SIM_GUI_ShowDevice() | Manages the visibility of the device bitmap. |
| SIM_GUI_SetCallback() | Sets a callback function for receiving the handles of the simulation windows. |
| SIM_GUI_SetCompositeColor() | Sets the background color of the composite window. (Only used with multi layer systems) |
| SIM_GUI_SetCompositeSize() | Sets the size of the composite window. (Only used with multi layer systems) |
| SIM_GUI_SetLCDColorBlack() | Set the color to be used as black (color monochrome displays). |
| SIM_GUI_SetLCDColorWhite() | Set the color to be used as white (color monochrome displays). |
| SIM_GUI_SetLCDPos() | Set the position for the simulated LCD within the target device bitmap. |
| SIM_GUI_SetMag() | Set magnification factors for X and/or Y axis. |
| SIM_GUI_SetTransColor() | Set the color to be used for transparent areas (default: 0xFF0000). |
| SIM_GUI_UseCustomBitmaps() | Tells the simulation to use the custom bitmaps from the application resource file. |
Hardkey simulation
The hardkey simulation can only be used in the custom bitmap view. Hardkeys may also be simulated as part of the device, and may be selected with the mouse pointer. The idea is to be able to distinguish whether a key or button on the simulated device is pressed or unpressed. A hardkey is considered "pressed" as long as the mouse button is held down; releasing the mouse button or moving the pointer off of the hardkey "unpresses" the key. A toggle behavior between pressed and unpressed may also be specified with the routine SIM_HARDKEY_SetMode().
In order to simulate hardkeys, you need a second bitmap of the device which is transparent except for the keys themselves (in their pressed state). As described earlier in this chapter, this bitmap can be in a separate file in the directory, or included as a resource in the executable. Hardkeys may be any shape, as long as they are exactly the same size in pixels in both Device.bmp and Device1.bmp. The following example illustrates this:
| Device bitmap: unpressed hardkey state (Device.bmp) | Device hardkey bitmap: pressed hardkey state (Device1.bmp) |
|---|---|
![]() | ![]() |
When a key is "pressed" with the mouse, the corresponding section of the hardkey bitmap (Device1.bmp) will overlay the device bitmap in order to display the key in its pressed state.
The keys may be polled periodically to determine if their states (pressed/unpressed) have changed and whether they need to be updated. Alternatively, a callback routine may be set to trigger a particular action to be carried out when the state of a hardkey changes.
Hardkey simulation API
The hardkey simulation functions are part of the standard simulation program shipped with emWin. If using a user defined emWin simulation these functions may not be available. The table below lists the available hardkey-simulation-related routines in alphabetical order within their respective categories:
| Routine | Explanation |
|---|---|
| SIM_HARDKEY_GetNum() | Return the number of available hardkeys. |
| SIM_HARDKEY_GetState() | Return the state of a specified hardkey (0: unpressed, 1: pressed). |
| SIM_HARDKEY_SetCallback() | Set a callback routine to be executed when the state of a specified hardkey changes. |
| SIM_HARDKEY_SetMode() | Set the behavior for a specified hardkey (default = 0: no toggle). |
| SIM_HARDKEY_SetState() | Set the state for a specified hardkey (0: unpressed, 1: pressed). |
Integrating the emWin simulation into an existing simulation
In order to integrate the emWin simulation into an existing simulation, the source code of the simulation is not required. The source code of the simulation is not normally shipped with emWin. It is a separate (optional) software item and is not included in the emWin basic package.
Normally the source code of the emWin simulation is not needed but available as an optional software item. As described earlier in this chapter the basic package and the trial version contains a simulation library. The API functions of this library can be used if for example the emWin simulation should be added to an existing hardware or real time kernel (RTOS) simulation.
To add the emWin simulation to an existing simulation (written in C or C++, using the Win32 API), only a few lines of code need to be added.
Directory structureThe subfolder Simulation of the System folder contains the emWin simulation. The directory structure is shown on the right. The table below explains the contents of the subfolders: | ![]() |
| Directory | Content |
|---|---|
| Simulation | Simulation source and header files to be used with and without the simulation source code. The folder also contains a ready to use simulation library. |
| Res | Resource files. |
| SIM_GUI | GUI simulation source code (optional). |
| WinMain | Contains the WinMain routine. |
Using the simulation library
The following steps will show how to use the simulation library to integrate the emWin simulation into an existing simulation:
- Step 1: Add the simulation library GUISim.lib to the project.
- Step 2: Add all GUI files to the project as described in the chapter 2.1.1, "Subdirectories".
- Step 3: Add the include directories to the project as described in the chapter 2.1.2, "Include Directories".
- Step 4: Modify WinMain.
Modifying WinMain
Every windows Win32 program starts with WinMain() (contrary to a normal C program from the command line, which starts with main(). All that needs to be done is to add a few lines of code to this routine.
The following function calls need to be added (normally in the order as it’s shown in the following application code example):
- SIM_GUI_Enable
- SIM_GUI_Init
- SIM_GUI_CreateLCDWindow
- CreateThread
- SIM_GUI_Exit
Example application
The following application is available under Sample\WinMain\SampleApp.c and shows how to integrate the emWin simulation into an existing application:
#include <windows.h>
#include "GUI_SIM_Win32.h"
void MainTask(void);
/*********************************************************************
*
* _Thread
*/
static DWORD __stdcall _Thread(void * Parameter) {
MainTask();
return 0;
}
/*********************************************************************
*
* _WndProcMain
*/
static LRESULT CALLBACK _WndProcMain(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam) {
SIM_GUI_HandleKeyEvents(message, wParam);
switch (message) {
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
/*********************************************************************
*
* _RegisterClass
*/
static void _RegisterClass(HINSTANCE hInstance) {
WNDCLASSEX wcex;
memset(&wcex, 0, sizeof(wcex));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.hInstance = hInstance;
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)_WndProcMain;
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
wcex.lpszMenuName = 0;
wcex.lpszClassName = "GUIApplication";
RegisterClassEx(&wcex);
}
/*********************************************************************
*
* WinMain
*/
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
DWORD ThreadID;
MSG Msg;
HWND hWndMain;
//
// Register window class
//
_RegisterClass(hInstance);
//
// Make sure the driver configuration is done
//
SIM_GUI_Enable();
//
// Create main window
//
hWndMain = CreateWindow("GUIApplication", "Application window",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE,
0, 0, 328, 267, NULL, NULL, hInstance, NULL);
//
// Initialize the emWin simulation and create an LCD window
//
SIM_GUI_Init(hInstance, hWndMain, lpCmdLine, "embOS - emWin Simulation");
SIM_GUI_CreateLCDWindow(hWndMain, 0, 0, 320, 240, 0);
//
// Create a thread which executes the code to be simulated
//
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)_Thread, NULL, 0, &ThreadID);
//
// Main message loop
//
while (GetMessage(&Msg, NULL, 0, 0)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
SIM_GUI_Exit();
} Integration into the embOS Simulation
WinMain
The following code example shows how to modify the existing WinMain of the embOS simulation in order to integrate the emWin simulation. The red colored lines should be added to WinMain to initialize the emWin simulation, to create a simulation window and to exit the emWin simulation:
...
#include "GUI_SIM_Win32.h"
...
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
MSG Msg;
HACCEL hAccelTable;
HWND hWndMain;
BITMAP BmpDevice;
DWORD ThreadID;
//
// Init global data
//
_StopHyperThreading();
_hInst = hInstance;
//
// Register main window class
//
_RegisterClass();
//
// Load bitmap
//
_hBmpDevice = (HBITMAP)LoadImage(_hInst, (LPCTSTR) IDB_DEVICE,
IMAGE_BITMAP, 0, 0, 0);
_hMenuPopup = LoadMenu(_hInst, (LPCSTR)IDC_CONTEXTMENU);
_hMenuPopup = GetSubMenu(_hMenuPopup, 0);
//
// Make sure the driver configuration is done
//
SIM_GUI_Enable();
//
// Create main window
//
GetObject(_hBmpDevice, sizeof(BmpDevice), &BmpDevice);
hWndMain = CreateWindowEx(WS_EX_TOPMOST, _sWindowClass, "embOS Simulation",
WS_SYSMENU | WS_CLIPCHILDREN | WS_POPUP | WS_VISIBLE,
10, 20, BmpDevice.bmWidth, BmpDevice.bmHeight,
NULL, NULL, _hInst, NULL);
if (!hWndMain) {
return 1; // Error
}
//
// Init emWin simulation and create window
//
SIM_GUI_Init(hInstance, hWndMain, lpCmdLine, "embOS - emWin Simulation");
SIM_GUI_CreateLCDWindow(hWndMain, 80, 50, 128, 64, 0);
//
// Show main window
//
ShowWindow(hWndMain, nCmdShow);
//
// Load accelerator table
//
hAccelTable = LoadAccelerators(_hInst, (LPCTSTR)IDC_WINMAIN);
//
// Application initialization
//
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread, NULL, 0, &ThreadID);
//
// Main message loop
//
if (SIM_Init(hWndMain) == 0) {
while (GetMessage(&Msg, NULL, 0, 0)) {
if (!TranslateAccelerator(Msg.hwnd, hAccelTable, &Msg)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
}
//
// Exit emWin simulation
//
SIM_GUI_Exit();
return 0;
} Target program (main)
The emWin API can be called from one or more target threads. Without RTOS, the WIN32 API function CreateThread is normally used to create a target thread which calls the emWin API; within an RTOS simulation, a target task/thread (Created by the simulated RTOS) is used to call the emWin API. In other words: Use OS_CreateTask to create a task for the user interface. Below a modified embOS start application:
#include <windows.h>
#include "RTOS.H"
#include "HW_LED.h"
#include "GUI.h"
OS_STACKPTR int Stack0[128], Stack1[128], Stack2[2000]; // Task stacks
OS_TASK TCB0, TCB1, TCB2; // Task-control-blocks
void Task0(void) {
while (1) {
HW_LED_Toggle0();
OS_Delay(100);
}
}
void Task1(void) {
while (1) {
HW_LED_Toggle1();
OS_Delay(500);
}
}
void MainTask(void) {
int i;
GUI_COLOR aColor[] = {GUI_RED, GUI_YELLOW};
GUI_Init();
while (1) {
for (i = 0; i < 2; i++) {
GUI_Clear();
GUI_SetColor(aColor[i]);
GUI_SetFont(&GUI_FontComic24B_ASCII);
GUI_DispStringAt("Hello world!", 1, 1);
OS_Delay(200);
}
}
}
/**********************************************************
*
* main
*/
void main(void) {
OS_IncDI(); // Initially disable interrupts
OS_InitKern(); // Initialize OS
OS_InitHW(); // Initialize Hardware for OS
//
// You need to create at least one task here
//
OS_CREATETASK(&TCB0, "HP Task", Task0, 100, Stack0);
OS_CREATETASK(&TCB1, "LP Task", Task1, 50, Stack1);
OS_CREATETASK(&TCB2, "GUI Task", MainTask, 80, Stack2);
OS_Start(); // Start multitasking
}
The following table shows the simulation before and after integrating the emWin simulation:
| Before | After |
|---|---|
![]() | ![]() |
GUI simulation API
The table below lists the available routines for user defined simulation programs in alphabetical order within their respective categories. The functions are only available with the source code of the emWin simulation:
| Routine | Explanation |
|---|---|
| SIM_GUI_CreateLCDInfoWindow() | Creates a window which shows the available colors of the given layer with the given size and position. |
| SIM_GUI_CreateLCDWindow() | Creates a LCD window with the given size and position. |
| SIM_GUI_Enable() | Executes memory and driver configuration. |
| SIM_GUI_Exit() | Stops the GUI simulation. |
| SIM_GUI_Init() | Initializes the GUI simulation. |
| SIM_GUI_SetLCDWindowHook() | Sets a hook function to be called if the LCD window receives a message. |
Simulation


















