1
/* $Id: main_wm.c 3553 2011-05-05 06:14:19Z nanang $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30
#define MAINWINDOWCLASS TEXT("SysTestDlg")
31
#define MAINWINDOWTITLE TEXT("PJSYSTEST")
33
typedef struct menu_handler_t {
35
gui_menu_handler handler;
38
static HINSTANCE g_hInst;
39
static HWND g_hWndMenuBar;
40
static HWND g_hWndMain;
41
static HWND g_hWndLog;
42
static pj_thread_t *g_log_thread;
43
static gui_menu *g_menu;
44
static unsigned g_menu_handler_cnt;
45
static menu_handler_t g_menu_handlers[64];
47
static pj_log_func *g_log_writer_orig;
49
static pj_status_t gui_update_menu(gui_menu *menu);
51
static void log_writer(int level, const char *buffer, int len)
58
pj_ansi_to_unicode(buffer, len, buf, 512);
63
/* For now, ignore log messages from other thread to avoid deadlock */
64
if (g_log_thread == pj_thread_this()) {
65
cur_len = (int)SendMessage(g_hWndLog, WM_GETTEXTLENGTH, 0, 0);
66
SendMessage(g_hWndLog, EM_SETSEL, (WPARAM)cur_len, (LPARAM)cur_len);
67
SendMessage(g_hWndLog, EM_REPLACESEL, (WPARAM)0, (LPARAM)buf);
70
//uncomment to forward to the original log writer
71
if (g_log_writer_orig)
72
(*g_log_writer_orig)(level, buffer, len);
75
/* execute menu handler for id menu specified, return FALSE if menu handler
78
static BOOL handle_menu(UINT id)
82
for (i = 0; i < g_menu_handler_cnt; ++i) {
83
if (g_menu_handlers[i].id == id) {
84
/* menu handler found, execute it */
85
(*g_menu_handlers[i].handler)();
93
/* generate submenu and register the menu handler, then return next menu id */
94
static UINT generate_submenu(HMENU parent, UINT id_start, gui_menu *menu)
102
/* generate submenu */
103
for (i = 0; i < menu->submenu_cnt; ++i) {
105
if (menu->submenus[i] == NULL) {
108
AppendMenu(parent, MF_SEPARATOR, 0, 0);
110
} else if (menu->submenus[i]->submenu_cnt != 0) {
112
/* this submenu item has children, generate popup menu */
116
pj_ansi_to_unicode(menu->submenus[i]->title,
117
pj_ansi_strlen(menu->submenus[i]->title),
120
hMenu = CreatePopupMenu();
121
AppendMenu(parent, MF_STRING|MF_ENABLED|MF_POPUP, (UINT)hMenu, buf);
122
id = generate_submenu(hMenu, id, menu->submenus[i]);
126
/* this submenu item is leaf, register the handler */
129
pj_ansi_to_unicode(menu->submenus[i]->title,
130
pj_ansi_strlen(menu->submenus[i]->title),
133
AppendMenu(parent, MF_STRING, id, buf);
135
if (menu->submenus[i]->handler) {
136
g_menu_handlers[g_menu_handler_cnt].id = id;
137
g_menu_handlers[g_menu_handler_cnt].handler =
138
menu->submenus[i]->handler;
139
++g_menu_handler_cnt;
152
if (gui_update_menu(g_menu) != PJ_SUCCESS)
158
LRESULT CALLBACK DialogProc(const HWND hWnd,
168
if (FALSE == InitDialog()){
169
DestroyWindow(g_hWndMain);
174
DestroyWindow(g_hWndMain);
179
DestroyWindow(g_hWndMenuBar);
180
g_hWndMenuBar = NULL;
186
/* Exit app when back is pressed. */
187
if (VK_TBACK == HIWORD(lParam) && (0 != (MOD_KEYUP & LOWORD(lParam)))) {
188
DestroyWindow(g_hWndMain);
190
return DefWindowProc(hWnd, Msg, wParam, lParam);
195
res = handle_menu(LOWORD(wParam));
199
return DefWindowProc(hWnd, Msg, wParam, lParam);
208
pj_status_t gui_init(gui_menu *menu)
215
pj_status_t status = PJ_SUCCESS;
217
/* Check if app is running. If it's running then focus on the window */
218
hWnd = FindWindow(MAINWINDOWCLASS, MAINWINDOWTITLE);
221
SetForegroundWindow(hWnd);
227
wc.style = CS_HREDRAW | CS_VREDRAW;
228
wc.lpfnWndProc = (WNDPROC)DialogProc;
231
wc.hInstance = g_hInst;
234
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
236
wc.lpszClassName = MAINWINDOWCLASS;
238
if (!RegisterClass(&wc) != 0) {
239
DWORD err = GetLastError();
240
return PJ_RETURN_OS_ERROR(err);
243
/* Create the app. window */
244
g_hWndMain = CreateWindow(MAINWINDOWCLASS, MAINWINDOWTITLE,
245
WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
246
CW_USEDEFAULT, CW_USEDEFAULT,
247
(HWND)NULL, NULL, g_hInst, (LPSTR)NULL);
249
/* Create edit control to print log */
250
GetClientRect(g_hWndMain, &r);
251
dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL |
252
ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | ES_LEFT;
253
g_hWndLog = CreateWindow(
254
TEXT("EDIT"), // Class name
256
dwStyle, // Window style
257
0, // x-coordinate of the upper-left corner
258
0, // y-coordinate of the upper-left corner
259
r.right-r.left, // Width of the window for the edit
261
r.bottom-r.top, // Height of the window for the edit
263
g_hWndMain, // Window handle to the parent window
264
(HMENU) 0, // Control identifier
265
g_hInst, // Instance handle
266
NULL); // Specify NULL for this parameter when
267
// you create a control
273
GetWindowRect(g_hWndLog, &r);
274
GetWindowRect(g_hWndMenuBar, &r_menu);
275
if (r.bottom > r_menu.top) {
276
MoveWindow(g_hWndLog, 0, 0, r.right-r.left,
277
(r.bottom-r.top)-(r_menu.bottom-r_menu.top), TRUE);
281
/* Focus it, so SP user can scroll the log */
284
/* Get the log thread */
285
g_log_thread = pj_thread_this();
287
/* Redirect log & update log decor setting */
289
log_decor = pj_log_get_decor();
290
log_decor = PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_CR;
291
pj_log_set_decor(log_decor);
293
g_log_writer_orig = pj_log_get_log_func();
294
pj_log_set_log_func(&log_writer);
299
static pj_status_t gui_update_menu(gui_menu *menu)
301
enum { MENU_ID_START = 50000 };
302
UINT id_start = MENU_ID_START;
306
/* delete existing menu */
308
DestroyWindow(g_hWndMenuBar);
309
g_hWndMenuBar = NULL;
312
/* delete menu handler map */
313
g_menu_handler_cnt = 0;
315
/* smartphone can only have two root menus */
316
pj_assert(menu->submenu_cnt <= 2);
318
/* generate menu tree */
319
hRootMenu = CreateMenu();
320
id_start = generate_submenu(hRootMenu, id_start, menu);
322
/* initialize menubar */
323
ZeroMemory(&mbi, sizeof(SHMENUBARINFO));
324
mbi.cbSize = sizeof(SHMENUBARINFO);
325
mbi.hwndParent = g_hWndMain;
326
mbi.dwFlags = SHCMBF_HIDESIPBUTTON|SHCMBF_HMENU;
327
mbi.nToolBarId = (UINT)hRootMenu;
328
mbi.hInstRes = g_hInst;
330
if (FALSE == SHCreateMenuBar(&mbi)) {
331
DWORD err = GetLastError();
332
return PJ_RETURN_OS_ERROR(err);
335
/* store menu window handle */
336
g_hWndMenuBar = mbi.hwndMB;
338
/* store current menu */
342
DrawMenuBar(g_hWndMain);
343
ShowWindow(g_hWndMenuBar, SW_SHOW);
345
/* override back button */
346
SendMessage(g_hWndMenuBar, SHCMBM_OVERRIDEKEY, VK_TBACK,
347
MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY,
348
SHMBOF_NODEFAULT | SHMBOF_NOTIFY));
354
enum gui_key gui_msgbox(const char *title, const char *message, enum gui_flag flag)
356
wchar_t buf_title[64];
357
wchar_t buf_msg[512];
361
pj_ansi_to_unicode(title, pj_ansi_strlen(title), buf_title, 64);
362
pj_ansi_to_unicode(message, pj_ansi_strlen(message), buf_msg, 512);
376
retcode = MessageBox(g_hWndMain, buf_msg, buf_title, wflag);
390
void gui_sleep(unsigned sec)
392
pj_thread_sleep(sec * 1000);
395
pj_status_t gui_start(gui_menu *menu)
401
while (GetMessage(&msg, NULL, 0, 0)) {
402
TranslateMessage(&msg);
403
DispatchMessage(&msg);
409
void gui_destroy(void)
412
DestroyWindow(g_hWndMain);
420
HINSTANCE hPrevInstance,
427
PJ_UNUSED_ARG(hPrevInstance);
428
PJ_UNUSED_ARG(lpCmdLine);
429
PJ_UNUSED_ARG(nShowCmd);
431
// store the hInstance in global
434
status = systest_init();
438
status = systest_run();