summaryrefslogtreecommitdiff
path: root/gui/win32
diff options
context:
space:
mode:
Diffstat (limited to 'gui/win32')
-rw-r--r--gui/win32/Makefile.am10
-rw-r--r--gui/win32/ceglue.c77
-rw-r--r--gui/win32/ceglue.h16
-rw-r--r--gui/win32/gui_win32.c643
-rw-r--r--gui/win32/resources/navit.icobin0 -> 10134 bytes
-rw-r--r--gui/win32/resources/resource.h4
-rw-r--r--gui/win32/resources/resource.rc14
-rw-r--r--gui/win32/resources/toolbar.bmpbin0 -> 1398 bytes
-rw-r--r--gui/win32/win32_gui_destination.c412
-rw-r--r--gui/win32/win32_gui_notify.c132
-rw-r--r--gui/win32/win32_gui_notify.h18
11 files changed, 1326 insertions, 0 deletions
diff --git a/gui/win32/Makefile.am b/gui/win32/Makefile.am
new file mode 100644
index 00000000..06d91fac
--- /dev/null
+++ b/gui/win32/Makefile.am
@@ -0,0 +1,10 @@
+include $(top_srcdir)/Makefile.inc
+AM_CPPFLAGS = -I$(top_srcdir)/navit -I$(top_srcdir)/navit/graphics/win32 @NAVIT_CFLAGS@ -DMODULE=gui_win32
+if PLUGINS
+modulegui_LTLIBRARIES = libgui_win32.la
+else
+noinst_LTLIBRARIES = libgui_win32.la
+endif
+libgui_win32_la_SOURCES = gui_win32.c win32_gui_destination.c win32_gui_notify.c ceglue.h ceglue.c
+libgui_win32_la_LIBADD =
+libgui_win32_la_LDFLAGS = -module -avoid-version
diff --git a/gui/win32/ceglue.c b/gui/win32/ceglue.c
new file mode 100644
index 00000000..a0817f93
--- /dev/null
+++ b/gui/win32/ceglue.c
@@ -0,0 +1,77 @@
+#include <windows.h>
+#include "ceglue.h"
+
+BOOL FAR (*SHFullScreenPtr)(HWND hwnd, DWORD state) = NULL;
+
+void InitCeGlue (void)
+{
+ HINSTANCE ayg = LoadLibraryW (TEXT ("aygshell.dll"));
+ if (ayg != NULL) {
+ SHFullScreenPtr = (BOOL (*)(HWND, DWORD))
+ GetProcAddressW (ayg, TEXT ("SHFullScreen"));
+ }
+}
+
+// code to turn of screen adopted from
+// http://msdn.microsoft.com/en-us/library/ms838354.aspx
+
+// GDI Escapes for ExtEscape()
+#define QUERYESCSUPPORT 8
+
+// The following are unique to CE
+#define GETVFRAMEPHYSICAL 6144
+#define GETVFRAMELEN 6145
+#define DBGDRIVERSTAT 6146
+#define SETPOWERMANAGEMENT 6147
+#define GETPOWERMANAGEMENT 6148
+
+
+typedef enum _VIDEO_POWER_STATE {
+ VideoPowerOn = 1,
+ VideoPowerStandBy,
+ VideoPowerSuspend,
+ VideoPowerOff
+} VIDEO_POWER_STATE, *PVIDEO_POWER_STATE;
+
+
+typedef struct _VIDEO_POWER_MANAGEMENT {
+ ULONG Length;
+ ULONG DPMSVersion;
+ ULONG PowerState;
+} VIDEO_POWER_MANAGEMENT, *PVIDEO_POWER_MANAGEMENT;
+
+
+int CeEnableBacklight(int enable)
+{
+ HDC gdc;
+ int iESC=SETPOWERMANAGEMENT;
+
+ gdc = GetDC(NULL);
+ if (ExtEscape(gdc, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&iESC,
+ 0, NULL)==0)
+ {
+ MessageBox(NULL,
+ L"Sorry, your Pocket PC does not support DisplayOff",
+ L"Pocket PC Display Off Feature",
+ MB_OK);
+ ReleaseDC(NULL, gdc);
+ return FALSE;
+ }
+ else
+ {
+ VIDEO_POWER_MANAGEMENT vpm;
+ vpm.Length = sizeof(VIDEO_POWER_MANAGEMENT);
+ vpm.DPMSVersion = 0x0001;
+ if (enable) {
+ vpm.PowerState = VideoPowerOn;
+ } else {
+ vpm.PowerState = VideoPowerOff;
+ }
+ // Power off the display
+ ExtEscape(gdc, SETPOWERMANAGEMENT, vpm.Length, (LPCSTR) &vpm,
+ 0, NULL);
+ ReleaseDC(NULL, gdc);
+ return TRUE;
+ }
+}
+
diff --git a/gui/win32/ceglue.h b/gui/win32/ceglue.h
new file mode 100644
index 00000000..b0dc79d4
--- /dev/null
+++ b/gui/win32/ceglue.h
@@ -0,0 +1,16 @@
+#ifndef CEGLUE_H
+#define CEGLUE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern BOOL (*SHFullScreenPtr)(HWND hwnd, DWORD state);
+void InitCeGlue (void);
+
+int CeEnableBacklight(int enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gui/win32/gui_win32.c b/gui/win32/gui_win32.c
new file mode 100644
index 00000000..3596496a
--- /dev/null
+++ b/gui/win32/gui_win32.c
@@ -0,0 +1,643 @@
+#include <stdlib.h>
+#include <process.h>
+#include <windows.h>
+#include <glib.h>
+#include "config.h"
+#include "plugin.h"
+#include "gui.h"
+#include "graphics_win32.h"
+#include "point.h"
+#include "menu.h"
+#include "item.h"
+#include "attr.h"
+#include "callback.h"
+#include <commctrl.h>
+#include "debug.h"
+#include "util.h"
+#include "navit.h"
+#include "navit_nls.h"
+#ifdef __CEGCC__
+#include <sipapi.h>
+#include <aygshell.h>
+#include "ceglue.h"
+
+static int ce_backlight = 1;
+static int ce_fullscreen;
+#endif
+
+#ifdef HAVE_GLIB
+//static GHashTable *popup_callback_hash = NULL;
+static GArray *popup_menu_array;
+#endif
+
+const TCHAR g_szClassName[] = TEXT("navit_gui_class");
+
+
+static UINT_PTR menu_id = 0;
+
+#if 0
+static gboolean message_pump( gpointer data )
+{
+ MSG messages;
+
+ Sleep( 1 );
+
+ if (GetMessage (&messages, NULL, 0, 0))
+ {
+ TranslateMessage(&messages);
+ DispatchMessage(&messages);
+ }
+ else{
+ exit( 0 );
+ }
+ return TRUE;
+}
+
+static BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
+{
+ LPRECT rcParent;
+ int idChild;
+
+ idChild = GetWindowLong(hwndChild, GWL_ID);
+
+ if ( idChild == ID_CHILD_GFX )
+ {
+ rcParent = (LPRECT) lParam;
+
+ MoveWindow( hwndChild, 0, 0, rcParent->right, rcParent->bottom, TRUE );
+ PostMessage( hwndChild, WM_USER+1, 0, 0 );
+ }
+
+ return TRUE;
+}
+#endif
+
+#ifndef GET_WHEEL_DELTA_WPARAM
+ #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
+#endif
+
+static void CreateToolBar(HWND hwnd)
+{
+ // Create Toolbar
+ HWND hTool;
+ TBBUTTON tbb[8];
+ TBADDBITMAP tbab;
+#if 0 /* def _WIN32_WCE */
+ /* Have to initialize common controls under CE */
+ INITCOMMONCONTROLSEX iccex;
+ iccex.dwSize = sizeof (INITCOMMONCONTROLSEX);
+ iccex.dwICC = ICC_BAR_CLASSES;
+ InitCommonControlsEx (&iccex);
+#else
+ InitCommonControls();
+#endif
+
+ hTool = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
+ hwnd, (HMENU)ID_CHILD_TOOLBAR, GetModuleHandle(NULL), NULL);
+
+ if(hTool == NULL)
+ MessageBox(hwnd, TEXT("Could not create tool bar."), TEXT("Error"), MB_OK | MB_ICONERROR);
+
+ SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
+
+ tbab.hInst = GetModuleHandle(NULL);
+ tbab.nID = IDB_NAVITTOOLBAR;
+ int iImageOffset = SendMessage(hTool, TB_ADDBITMAP, 10, (LPARAM) &tbab);
+
+ int iStr;
+
+ ZeroMemory(tbb, sizeof(tbb));
+
+ tbb[0].iBitmap = iImageOffset;
+ tbb[0].fsState = TBSTATE_ENABLED;
+ tbb[0].fsStyle = TBSTYLE_BUTTON;
+ tbb[0].idCommand = ID_DISPLAY_ZOOMIN;
+ iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM) L"ZoomIn" );
+ tbb[0].iString = iStr;
+
+ tbb[1].iBitmap = iImageOffset+1;
+ tbb[1].fsState = TBSTATE_ENABLED;
+ tbb[1].fsStyle = TBSTYLE_BUTTON;
+ tbb[1].idCommand = ID_DISPLAY_ZOOMOUT;
+ iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM) L"ZoomOut" );
+ tbb[1].iString = iStr;
+
+ tbb[2].iBitmap = iImageOffset+4;
+ tbb[2].fsState = TBSTATE_ENABLED;
+ tbb[2].fsStyle = TBSTYLE_BUTTON;
+ tbb[2].idCommand = ID_DISPLAY_REFRESH;
+ iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM) L"Refresh" );
+ tbb[2].iString = iStr;
+
+ tbb[3].iBitmap = iImageOffset+2;
+ tbb[3].fsState = TBSTATE_ENABLED;
+ tbb[3].fsStyle = TBSTYLE_BUTTON;
+ tbb[3].idCommand = ID_DISPLAY_ZOOMIN;
+ iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM) L"Cursor" );
+ tbb[3].iString = iStr;
+
+ tbb[4].iBitmap = iImageOffset+5;
+ tbb[4].fsState = TBSTATE_ENABLED;
+ tbb[4].fsStyle = TBSTYLE_BUTTON;
+ tbb[4].idCommand = ID_DISPLAY_ORIENT;
+ iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM) L"Orientation" );
+ tbb[4].iString = iStr;
+
+ tbb[5].iBitmap = iImageOffset+8;
+ tbb[5].fsState = TBSTATE_ENABLED;
+ tbb[5].fsStyle = TBSTYLE_BUTTON;
+ tbb[5].idCommand = ID_DISPLAY_ZOOMIN;
+ iStr= SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM) L"Destination" );
+ tbb[5].iString = iStr;
+
+ tbb[6].iBitmap = iImageOffset+3;
+ tbb[6].fsState = TBSTATE_ENABLED;
+ tbb[6].fsStyle = TBSTYLE_BUTTON;
+ tbb[6].idCommand = ID_DISPLAY_ZOOMIN;
+ iStr= SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM) L"Roadbook" );
+ tbb[6].iString = iStr;
+
+ tbb[7].iBitmap = iImageOffset+9;
+ tbb[7].fsState = TBSTATE_ENABLED;
+ tbb[7].fsStyle = TBSTYLE_BUTTON;
+ tbb[7].idCommand = ID_FILE_EXIT;
+ iStr= SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM) L"_Quit" );
+ tbb[7].iString = iStr;
+
+ SendMessage(hTool, TB_ADDBUTTONS, sizeof(tbb)/sizeof(TBBUTTON), (LPARAM)&tbb);
+}
+
+static void window_layout( HWND hwnd )
+{
+#ifndef HAVE_API_WIN32_CE
+ RECT rcClient;
+ RECT rcTool;
+ int iToolHeight;
+
+ HWND hChild = GetDlgItem(hwnd, ID_CHILD_TOOLBAR);
+ SendMessage(hChild, TB_AUTOSIZE, 0, 0);
+
+ GetWindowRect(hChild, &rcTool);
+ iToolHeight = rcTool.bottom - rcTool.top;
+
+ GetClientRect(hwnd, &rcClient);
+ //printf( "BEFORE resize gui to: %d %d %d %d \n", rcClient.left, rcClient.right, rcClient.top, rcClient.bottom );
+
+ rcClient.top += iToolHeight;
+
+ dbg(0, "resize gui to: %d %d %d %d \n", rcClient.left, rcClient.right, rcClient.top, rcClient.bottom );
+
+
+ hChild = GetDlgItem(hwnd, ID_CHILD_GFX);
+ if ( hChild )
+ {
+ MoveWindow( hChild, rcClient.left, rcClient.top, rcClient.right- rcClient.left, rcClient.bottom - rcClient.top, TRUE );
+ PostMessage( hChild, WM_USER+1, 0, 0 );
+ }
+#endif
+}
+#ifdef __CEGCC__
+static void toggle_fullscreen(HWND mWnd)
+{
+ if (SHFullScreenPtr) {
+ if (!ce_fullscreen) {
+ (*SHFullScreenPtr)(mWnd, SHFS_HIDETASKBAR |
+ SHFS_HIDESTARTICON | SHFS_HIDESIPBUTTON);
+ } else {
+ (*SHFullScreenPtr)(mWnd, SHFS_HIDESIPBUTTON);
+ }
+ ce_fullscreen = !ce_fullscreen;
+ }
+}
+
+static void toggle_backlight(void)
+{
+ if (ce_backlight)
+ if (CeEnableBacklight(FALSE))
+ ce_backlight = 0;
+ else
+ if (CeEnableBacklight(TRUE))
+ ce_backlight = 1;
+}
+#endif
+
+static LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
+{
+ RECT rcClient;
+
+// printf( "PARENT %d %d %d \n", Message, wParam, lParam );
+
+ switch(Message)
+ {
+ case WM_CREATE:
+ {
+ HMENU hMenu, hSubMenu;
+
+ CreateToolBar( hwnd );
+
+ hMenu = CreateMenu();
+ // g_this_->hwnd = hwnd;
+
+ hSubMenu = CreatePopupMenu();
+
+ AppendMenuW(hSubMenu, MF_STRING, ID_DISPLAY_ZOOMIN, L"ZoomIn" );
+ AppendMenuW(hSubMenu, MF_STRING, ID_DISPLAY_ZOOMOUT, L"ZoomOut" );
+ AppendMenuW(hSubMenu, MF_STRING, ID_DISPLAY_REFRESH, L"Refresh" );
+ AppendMenuW(hSubMenu, MF_SEPARATOR, 0, NULL );
+ AppendMenuW(hSubMenu, MF_STRING, ID_FILE_EXIT, L"_Quit" );
+
+ AppendMenuW(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, L"Display" );
+ hSubMenu = CreatePopupMenu();
+ AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, TEXT("&Go"));
+ AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, TEXT("&Stuff"));
+
+#ifndef HAVE_API_WIN32_CE
+ SetMenu(hwnd, hMenu);
+#endif
+
+ window_layout( hwnd );
+
+ }
+ break;
+ case WM_COMMAND:
+ {
+ printf( "WM_COMMAND %d\n", LOWORD(wParam) );
+ struct gui_priv* gui = (struct gui_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
+
+
+ switch(LOWORD(wParam))
+ {
+ case ID_DISPLAY_ZOOMIN:
+ navit_zoom_in(gui->nav, 2, NULL);
+ return 0;
+ break;
+ case ID_DISPLAY_ZOOMOUT:
+ navit_zoom_out(gui->nav, 2, NULL);
+ return 0;
+ break;
+ case ID_DISPLAY_REFRESH:
+ navit_draw(gui->nav);
+ return 0;
+ break;
+ case ID_DISPLAY_CURSOR:
+ {
+ struct attr attr;
+ attr.type=attr_cursor;
+ // TODO attr.u.num=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w));
+ if(!navit_set_attr(gui->nav, &attr)) {
+ dbg(0, "Failed to set attr_cursor\n");
+ }
+ return 0;
+ }
+ break;
+ case ID_DISPLAY_ORIENT:
+ {
+ struct attr attr;
+
+ attr.type=attr_orientation;
+ // attr.u.num=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w));
+ attr.u.num = 0; // TODO
+ if(!navit_set_attr(gui->nav, &attr)) {
+ dbg(0, "Failed to set attr_orientation\n");
+ }
+ return 0;
+ }
+
+ case ID_FILE_EXIT:
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ return 0;
+ break;
+ }
+#if HAVE_GLIB
+ if ( popup_menu_array )
+ {
+ struct menu_priv* priv = (struct menu_priv*)g_array_index( popup_menu_array, gint, LOWORD(wParam) - POPUP_MENU_OFFSET );
+
+ if ( priv )
+ {
+ struct callback* cb = priv->cb;
+ if ( priv->cb )
+ {
+ callback_call_0( priv->cb );
+ return 0;
+ }
+ }
+ }
+#endif
+ }
+ break;
+ case WM_USER+ 1:
+ GetClientRect(hwnd, &rcClient);
+ printf( "resize gui to: %d %d \n", rcClient.right, rcClient.bottom );
+
+ window_layout( hwnd );
+ //EnumChildWindows(hwnd, EnumChildProc, (LPARAM) &rcClient);
+ return 0;
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwnd);
+ break;
+ case WM_SIZE:
+ window_layout( hwnd );
+ return 0;
+ break;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+
+
+ case WM_MOUSEWHEEL:
+ {
+ struct gui_priv* gui = (struct gui_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
+
+ short delta = GET_WHEEL_DELTA_WPARAM( wParam );
+ if ( delta > 0 )
+ {
+ navit_zoom_in(gui->nav, 2, NULL);
+ }
+ else{
+ navit_zoom_out(gui->nav, 2, NULL);
+ }
+ }
+ break;
+#ifdef HAVE_API_WIN32_CE
+ case WM_KEYDOWN:
+ {
+ struct point p;
+ int w,h;
+ struct gui_priv* gui = (struct gui_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
+ transform_get_size(navit_get_trans(gui->nav), &w, &h);
+
+ if (wParam == VK_LEFT || wParam == '4') {
+ p.x=0;
+ p.y=h/2;
+ navit_set_center_screen(gui->nav, &p, 1);
+ } else if (wParam == VK_RIGHT || wParam == '6') {
+ p.x=w;
+ p.y=h/2;
+ navit_set_center_screen(gui->nav, &p, 1);
+ } else if (wParam == VK_UP || wParam == '2') {
+ p.x=w/2;
+ p.y=0;
+ navit_set_center_screen(gui->nav, &p, 1);
+ } else if (wParam == VK_DOWN || wParam == '8') {
+ p.x=w/2;
+ p.y=h;
+ navit_set_center_screen(gui->nav, &p, 1);
+ } else if (wParam == '1') {
+ navit_zoom_in(gui->nav, 2, NULL);
+ } else if (wParam == '3') {
+ navit_zoom_out(gui->nav, 2, NULL);
+ } else if (wParam == '7') {
+#if 0
+ toggle_backlight();
+#endif
+ } else if (wParam == '9') {
+#if 0
+ toggle_fullscreen(hwnd);
+#endif
+ }
+ }
+ break;
+#endif
+ default:
+ return DefWindowProc(hwnd, Message, wParam, lParam);
+ }
+ return 0;
+}
+
+static HANDLE CreateWin32Window( void )
+{
+#ifdef HAVE_API_WIN32_CE
+ WNDCLASS wc;
+#else
+ WNDCLASSEX wc;
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.hIconSm = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_NAVIT));
+#endif
+ HWND hwnd;
+// MSG Msg;
+
+ wc.style = 0;
+ wc.lpfnWndProc = WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 32;
+ wc.hInstance = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = g_szClassName;
+ wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_NAVIT));
+
+#ifdef HAVE_API_WIN32_CE
+ if(!RegisterClass(&wc))
+#else
+ if(!RegisterClassEx(&wc))
+#endif
+
+ {
+ MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
+ return 0;
+ }
+
+ hwnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ g_szClassName,
+ TEXT( "Navit" ),
+#ifdef HAVE_API_WIN32_CE
+ WS_SYSMENU | WS_CLIPCHILDREN,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+#else
+
+ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
+ CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
+#endif
+ NULL, NULL, NULL, NULL);
+
+ if(hwnd == NULL)
+ {
+ MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
+ return 0;
+ }
+
+ ShowWindow(hwnd, TRUE);
+ UpdateWindow(hwnd);
+
+#if 0
+ g_idle_add (message_pump, NULL);
+#endif
+
+ return hwnd;
+}
+
+
+static int win32_gui_set_graphics(struct gui_priv *this_, struct graphics *gra)
+{
+ HANDLE* wndHandle_ptr = graphics_get_data(gra, "wnd_parent_handle_ptr");
+ *wndHandle_ptr = this_->hwnd;
+ graphics_get_data(gra, "START_CLIENT");
+ return 0;
+}
+
+
+static void win32_gui_add_bookmark_do(struct gui_priv *gui)
+{
+// navit_add_bookmark(gui->nav, &gui->dialog_coord, gtk_entry_get_text(GTK_ENTRY(gui->dialog_entry)));
+// gtk_widget_destroy(gui->dialog_win);
+}
+
+static int win32_gui_add_bookmark(struct gui_priv *gui, struct pcoord *c, char *description)
+{
+ return 1;
+}
+
+
+static struct menu_methods menu_methods;
+
+
+static struct menu_priv *add_menu( struct menu_priv *menu,
+ struct menu_methods *meth,
+ char *name,
+ enum menu_type type,
+ struct callback *cb)
+{
+ struct menu_priv* ret = NULL;
+
+ ret = g_new0(struct menu_priv, 1);
+
+ *ret = *menu;
+ *meth = menu_methods;
+
+ TCHAR *menuname = newSysString(name);
+
+ if ( type == menu_type_submenu )
+ {
+ HMENU hSubMenu = NULL;
+ hSubMenu = CreatePopupMenu();
+ AppendMenu(menu->hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, menuname );
+ ret->hMenu = hSubMenu;
+ }
+ else
+ {
+ AppendMenu( menu->hMenu, MF_STRING, menu_id, name );
+ }
+
+ // g_hash_table_insert( popup_callback_hash, GINT_TO_POINTER( menu_id ), (gpointer)cb );
+#if HAVE_GLIB
+ g_array_append_val( popup_menu_array, ret );
+#endif
+
+ ret->cb = cb;
+
+ menu_id++;
+
+ return ret;
+
+}
+
+static void set_toggle(struct menu_priv *menu, int active)
+{
+ // gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(menu->action), active);
+}
+
+static int get_toggle(struct menu_priv *menu)
+{
+ // return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(menu->action));
+ return 0;
+}
+
+static struct menu_methods menu_methods = {
+ add_menu,
+ set_toggle,
+ get_toggle,
+};
+
+static void popup_activate(struct menu_priv *menu)
+{
+ POINT pnt;
+ GetCursorPos( &pnt );
+
+ if (menu->hMenu)
+ {
+ TrackPopupMenu( menu->hMenu, 0, pnt.x, pnt.y, 0, menu->wnd_handle, NULL );
+ DestroyMenu( menu->hMenu );
+ }
+}
+
+
+static void popup_deactivate( struct menu_priv *menu )
+{
+ DestroyMenu( menu->hMenu );
+}
+
+static struct menu_priv* win32_gui_popup_new(struct gui_priv *this_, struct menu_methods *meth)
+{
+ struct menu_priv* ret = NULL;
+
+ ret = g_new0(struct menu_priv, 1);
+ *meth = menu_methods;
+
+ menu_id = POPUP_MENU_OFFSET;
+
+#if HAVE_GLIB
+ if ( popup_menu_array )
+ {
+ g_array_free (popup_menu_array, TRUE);
+ popup_menu_array = NULL;
+ }
+
+ popup_menu_array = g_array_new (FALSE, FALSE, sizeof (gint));
+#endif
+
+ ret->cb = NULL;
+ ret->hMenu = CreatePopupMenu();
+ ret->wnd_handle = this_->hwnd;
+ meth->popup=popup_activate;
+
+printf( "create popup menu %d \n", ret->hMenu );
+
+ return ret;
+}
+
+struct gui_methods win32_gui_methods = {
+ NULL, // win32_gui_menubar_new,
+ win32_gui_popup_new,
+ win32_gui_set_graphics,
+ NULL,
+ NULL, // win32_gui_datawindow_new,
+ win32_gui_add_bookmark,
+};
+
+
+
+static struct gui_priv *win32_gui_new( struct navit *nav, struct gui_methods *meth, struct attr **attrs)
+{
+ struct gui_priv *this_;
+#ifdef HAVE_API_WIN32_CE
+ /* Do not run multiple instances under CE */
+ HWND prev;
+ prev = FindWindow(g_szClassName, NULL);
+ if (prev) {
+ ShowWindow(prev, SW_RESTORE);
+ SetForegroundWindow(prev);
+ InvalidateRect (prev, NULL, FALSE);
+ exit(0);
+ }
+ InitCeGlue();
+#endif
+
+ *meth=win32_gui_methods;
+
+ this_=g_new0(struct gui_priv, 1);
+ this_->nav=nav;
+
+ this_->hwnd = CreateWin32Window();
+ SetWindowLongPtr( this_->hwnd , DWLP_USER, (LONG_PTR)this_ );
+
+ return this_;
+}
+
+void plugin_init(void)
+{
+ plugin_register_gui_type("win32", win32_gui_new);
+}
diff --git a/gui/win32/resources/navit.ico b/gui/win32/resources/navit.ico
new file mode 100644
index 00000000..6fd707da
--- /dev/null
+++ b/gui/win32/resources/navit.ico
Binary files differ
diff --git a/gui/win32/resources/resource.h b/gui/win32/resources/resource.h
new file mode 100644
index 00000000..55bcc2d7
--- /dev/null
+++ b/gui/win32/resources/resource.h
@@ -0,0 +1,4 @@
+#include <windows.h>
+
+#define IDI_NAVIT 1100
+#define IDB_NAVITTOOLBAR 1101
diff --git a/gui/win32/resources/resource.rc b/gui/win32/resources/resource.rc
new file mode 100644
index 00000000..d31d89c1
--- /dev/null
+++ b/gui/win32/resources/resource.rc
@@ -0,0 +1,14 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_NAVITTOOLBAR BITMAP DISCARDABLE "toolbar.bmp"
+IDI_NAVIT ICON DISCARDABLE "navit.ico"
diff --git a/gui/win32/resources/toolbar.bmp b/gui/win32/resources/toolbar.bmp
new file mode 100644
index 00000000..17381d83
--- /dev/null
+++ b/gui/win32/resources/toolbar.bmp
Binary files differ
diff --git a/gui/win32/win32_gui_destination.c b/gui/win32/win32_gui_destination.c
new file mode 100644
index 00000000..67eae07c
--- /dev/null
+++ b/gui/win32/win32_gui_destination.c
@@ -0,0 +1,412 @@
+#include <windows.h>
+#include <windowsx.h>
+#include <commctrl.h>
+#include <glib.h>
+#include "item.h"
+#include "attr.h"
+#include "navit.h"
+#include "search.h"
+#include "debug.h"
+#include "util.h"
+#include "win32_gui_notify.h"
+#include "resources/resource.h"
+
+static const TCHAR g_szDestinationClassName[] = TEXT("navit_gui_destinationwindow_class");
+
+struct datawindow_priv
+{
+ HWND hwnd;
+ HWND hwndLabel;
+ HWND hwndEdit;
+ HWND hwndList;
+ HWND hwndButtonPrev;
+ HWND hwndButtonNext;
+ enum attr_type currentSearchState;
+ struct search_list *sl;
+ struct navit *nav;
+ struct notify_priv *notifications;
+};
+
+static void setlayout(struct datawindow_priv *datawindow)
+{
+ LVCOLUMN lvc;
+ lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+
+ RECT winrect;
+ GetWindowRect (datawindow->hwndList, &winrect);
+
+ lvc.iSubItem = 1;
+ lvc.cx = (winrect.right - winrect.left) - 52 ;
+ lvc.fmt = LVCFMT_LEFT; // left-aligned column
+
+ switch (datawindow->currentSearchState)
+ {
+ case attr_country_name:
+ {
+ Edit_SetText(datawindow->hwndLabel, TEXT("Country"));
+ lvc.pszText = TEXT("Country");
+ }
+ break;
+ case attr_town_name:
+ {
+ Edit_SetText(datawindow->hwndLabel, TEXT("Postal or Town"));
+ lvc.pszText = TEXT("Town");
+ }
+ break;
+ case attr_street_name:
+ {
+ Edit_SetText(datawindow->hwndLabel, TEXT("Street"));
+ lvc.pszText = TEXT("Street");
+ }
+ break;
+ default:
+ break;
+
+ }
+
+ (void)ListView_SetColumn(datawindow->hwndList, 1, &lvc);
+
+ Edit_SetText(datawindow->hwndEdit, TEXT(""));
+ SetFocus(datawindow->hwndEdit);
+}
+
+static void notify_apply(struct datawindow_priv *datawindow, int index, int param2)
+{
+ TCHAR txtBuffer[1024];
+ char search_string[1024];
+ struct attr search_attr;
+ struct search_list_result *res;
+
+
+ if ( index >= 0 )
+ {
+ ListView_GetItemText(datawindow->hwndList, index, 1, txtBuffer, 1024);
+
+ TCHAR_TO_UTF8(txtBuffer, search_string);
+
+ search_attr.type = datawindow->currentSearchState;
+ search_attr.u.str = search_string;
+
+ search_list_search(datawindow->sl, &search_attr, 0);
+ res=search_list_get_result(datawindow->sl);
+ }
+
+ switch (datawindow->currentSearchState)
+ {
+ case attr_country_name:
+ {
+ datawindow->currentSearchState = attr_town_name;
+ }
+ break;
+ case attr_town_name:
+ {
+ datawindow->currentSearchState = attr_street_name;
+ }
+ break;
+ case attr_street_name:
+ {
+ navit_set_destination(datawindow->nav, res->c, "Mein Test", 1);
+ DestroyWindow(datawindow->hwnd);
+ }
+ break;
+ default:
+ break;
+
+ }
+
+ setlayout(datawindow);
+
+}
+
+static void notify_back(struct datawindow_priv *datawindow, int param1, int param2)
+{
+ switch (datawindow->currentSearchState)
+ {
+ case attr_country_name:
+ break;
+ case attr_town_name:
+ {
+ datawindow->currentSearchState = attr_country_name;
+ }
+ break;
+ case attr_street_name:
+ {
+ datawindow->currentSearchState = attr_town_name;
+ }
+ break;
+ default:
+ break;
+
+ }
+
+ setlayout(datawindow);
+}
+
+static void notify_textchange(struct datawindow_priv *datawindow, int param1, int param2)
+{
+
+ struct attr search_attr;
+ struct search_list_result *res;
+ char search_string[1024];
+ TCHAR converted_iso2[32];
+
+
+ int lineLength = Edit_LineLength(datawindow->hwndEdit, 0);
+ TCHAR line[lineLength + 1];
+ (void)Edit_GetLine(datawindow->hwndEdit, 0, line, lineLength + 1);
+ line[lineLength] = 0;
+
+
+ (void)ListView_DeleteAllItems( datawindow->hwndList);
+
+ TCHAR_TO_UTF8(line, search_string);
+
+ search_attr.type = datawindow->currentSearchState;
+ search_attr.u.str = search_string;
+
+ if (lineLength<1)
+ return;
+
+ search_list_search(datawindow->sl, &search_attr, 1);
+
+
+ TCHAR *tcharBuffer = NULL;
+ int listIndex = 0;
+ LVITEM lvI;
+
+ lvI.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvI.state = 0;
+ lvI.stateMask = 0;
+
+ while ((res=search_list_get_result(datawindow->sl)) && listIndex < 50)
+ {
+
+ switch (search_attr.type)
+ {
+ case attr_country_name:
+ tcharBuffer = newSysString(res->country->name);
+ break;
+ case attr_town_name:
+ tcharBuffer = newSysString(res->town->name);
+ break;
+ case attr_street_name:
+ if (res->street->name)
+ {
+ tcharBuffer = newSysString(res->street->name);
+ }
+ else
+ {
+ continue;
+ }
+ break;
+ default:
+ dbg(0, "Unhandled search type");
+ }
+
+ lvI.iItem = listIndex;
+ lvI.iImage = listIndex;
+ lvI.iSubItem = 0;
+ lvI.lParam = (LPARAM) res->country->iso2;
+ UTF8_TO_TCHAR(res->country->iso2, converted_iso2);
+ lvI.pszText = converted_iso2;//LPSTR_TEXTCALLBACK; // sends an LVN_GETDISP message.
+ (void)ListView_InsertItem(datawindow->hwndList, &lvI);
+ ListView_SetItemText(datawindow->hwndList, listIndex, 1, tcharBuffer);
+ g_free(tcharBuffer);
+ dbg(0,"%s\n", res->country->name);
+ listIndex++;
+ }
+}
+
+static void notify_destroy(struct datawindow_priv *datawindow, int param1, int param2)
+{
+ if ( datawindow )
+ {
+ search_list_destroy(datawindow->sl);
+ g_free(datawindow);
+ }
+}
+
+static void notify_size(struct datawindow_priv *datawindow, int width, int height)
+{
+ if (datawindow)
+ {
+ MoveWindow(datawindow->hwndLabel,
+ 0, 0, // starting x- and y-coordinates
+ width, // width of client area
+ 20, // height of client area
+ TRUE); // repaint window
+ MoveWindow(datawindow->hwndEdit,
+ 0, 20, // starting x- and y-coordinates
+ width, // width of client area
+ 20, // height of client area
+ TRUE); // repaint window
+ MoveWindow(datawindow->hwndList,
+ 0, 40, // starting x- and y-coordinates
+ width, // width of client area
+ height - 60, // height of client area
+ TRUE); // repaint window
+ MoveWindow(datawindow->hwndButtonPrev,
+ 0, height - 20, // starting x- and y-coordinates
+ width/2, // width of client area
+ 20, // height of client area
+ TRUE); // repaint window
+ MoveWindow(datawindow->hwndButtonNext,
+ width/2, height - 20, // starting x- and y-coordinates
+ width/2, // width of client area
+ 20, // height of client area
+ TRUE); // repaint window
+
+ setlayout(datawindow);
+
+ }
+}
+
+static BOOL init_lv_columns(HWND hWndListView)
+{
+
+// struct LVCOLUMN lvc = {LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
+// LVCFMT_LEFT, 100, szText[iCol], 0, iCol, 0, 0 };
+
+ TCHAR szText[][8] = {TEXT("Iso"),TEXT("Country")}; // temporary buffer
+ LVCOLUMN lvc;
+ int iCol;
+
+ lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+
+ for (iCol = 0; iCol < 2; iCol++)
+ {
+ lvc.iSubItem = iCol;
+ lvc.pszText = szText[iCol];
+ lvc.cx = 50; // width of column in pixels
+
+ if ( iCol < 2 )
+ lvc.fmt = LVCFMT_LEFT; // left-aligned column
+ else
+ lvc.fmt = LVCFMT_RIGHT; // right-aligned column
+
+ if (ListView_InsertColumn(hWndListView, iCol, &lvc) == -1)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL register_destination_window()
+{
+ WNDCLASS wc;
+
+ wc.style = 0;
+ wc.lpfnWndProc = message_handler;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 32;
+ wc.hInstance = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = g_szDestinationClassName;
+ wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_NAVIT));
+
+ if (!RegisterClass(&wc))
+ {
+ dbg(0, "Window Registration Failed!\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+HANDLE create_destination_window( struct navit *nav )
+{
+
+
+ struct datawindow_priv *this_;
+
+ this_=g_new0(struct datawindow_priv, 1);
+ this_->nav = nav;
+ this_->currentSearchState = attr_country_name;
+ this_->sl=search_list_new(navit_get_mapset(this_->nav));
+
+ this_->hwnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ g_szDestinationClassName,
+ TEXT("Destination Input"),
+#if defined(__CEGCC__)
+ WS_SYSMENU | WS_CLIPCHILDREN,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+#else
+ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
+ CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
+#endif
+ NULL, NULL, NULL, NULL);
+
+ if (this_->hwnd == NULL)
+ {
+ dbg(0, "Window Creation Failed!\n");
+ return 0;
+ }
+
+ this_->notifications = win32_gui_notify_new(this_);
+ SetWindowLongPtr( this_->hwnd , DWLP_USER, (LONG_PTR) this_->notifications );
+
+ this_->hwndLabel = CreateWindow(WC_STATIC, // predefined class
+ TEXT("Country"), // no window title
+ WS_CHILD | WS_VISIBLE | ES_LEFT , //| WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL
+ 0, 0, 0, 0, // set size in WM_SIZE message
+ this_->hwnd, // parent window
+ NULL,//(HMENU) ID_EDITCHILD, // edit control ID
+ (HINSTANCE) GetWindowLong(this_->hwnd, GWL_HINSTANCE),
+ NULL); // pointer not needed
+
+ this_->hwndEdit = CreateWindow(WC_EDIT, // predefined class
+ NULL, // no window title
+ WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER , //| WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL
+ 0, 0, 0, 0, // set size in WM_SIZE message
+ this_->hwnd, // parent window
+ NULL,//(HMENU) ID_EDITCHILD, // edit control ID
+ (HINSTANCE) GetWindowLong(this_->hwnd, GWL_HINSTANCE),
+ NULL); // pointer not needed
+
+ this_->hwndList = CreateWindow(WC_LISTVIEW, // predefined class
+ NULL, // no window title
+ WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER | LVS_REPORT , //| WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL
+ 0, 0, 0, 0, // set size in WM_SIZE message
+ this_->hwnd, // parent window
+ NULL,//(HMENU) ID_EDITCHILD, // edit control ID
+ (HINSTANCE) GetWindowLong(this_->hwnd, GWL_HINSTANCE),
+ NULL); // pointer not needed
+
+ this_->hwndButtonPrev = CreateWindow(WC_BUTTON, // predefined class
+ TEXT("<<"), // no window title
+ WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER | LVS_REPORT , //| WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL
+ 0, 0, 0, 0, // set size in WM_SIZE message
+ this_->hwnd, // parent window
+ NULL,//(HMENU) ID_EDITCHILD, // edit control ID
+ (HINSTANCE) GetWindowLong(this_->hwnd, GWL_HINSTANCE),
+ NULL); // pointer not needed
+ this_->hwndButtonNext = CreateWindow(WC_BUTTON, // predefined class
+ TEXT(">>"), // no window title
+ WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER | LVS_REPORT , //| WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL
+ 0, 0, 0, 0, // set size in WM_SIZE message
+ this_->hwnd, // parent window
+ NULL,//(HMENU) ID_EDITCHILD, // edit control ID
+ (HINSTANCE) GetWindowLong(this_->hwnd, GWL_HINSTANCE),
+ NULL); // pointer not needed
+#ifdef LVS_EX_FULLROWSELECT
+ (void)ListView_SetExtendedListViewStyle(this_->hwndList,LVS_EX_FULLROWSELECT);
+#endif
+
+
+ win32_gui_notify( this_->notifications, this_->hwndEdit, CHANGE, notify_textchange);
+ win32_gui_notify( this_->notifications, NULL, WINDOW_SIZE, notify_size);
+ win32_gui_notify( this_->notifications, this_->hwndList, DBLCLICK, notify_apply);
+ win32_gui_notify( this_->notifications, this_->hwnd, WINDOW_DESTROY, notify_destroy);
+
+ win32_gui_notify( this_->notifications, this_->hwndButtonNext, BUTTON_CLICK, notify_apply);
+ win32_gui_notify( this_->notifications, this_->hwndButtonPrev, BUTTON_CLICK, notify_back);
+
+ init_lv_columns(this_->hwndList);
+ SetFocus(this_->hwndEdit);
+ ShowWindow(this_->hwnd, TRUE);
+ UpdateWindow(this_->hwnd);
+
+ return this_->hwnd;
+}
+
diff --git a/gui/win32/win32_gui_notify.c b/gui/win32/win32_gui_notify.c
new file mode 100644
index 00000000..c801e9da
--- /dev/null
+++ b/gui/win32/win32_gui_notify.c
@@ -0,0 +1,132 @@
+#include <windows.h>
+#include <windowsx.h>
+#include <commctrl.h>
+#include <glib.h>
+#include "win32_gui_notify.h"
+
+struct window_data
+{
+ HWND hwnd;
+ UINT message;
+ void(*func)(struct datawindow_priv *parent, int param1, int param2);
+};
+
+struct notify_priv
+{
+ GList *window_list;
+ struct datawindow_priv *parent;
+
+};
+
+
+void win32_gui_notify(struct notify_priv* notify, HWND hwnd, int message_id, void(*func)(struct datawindow_priv *parent, int param1, int param2))
+{
+ struct window_data *wnd_data = g_new( struct window_data,1);
+
+ wnd_data->hwnd = hwnd;
+ wnd_data->message = message_id;
+ wnd_data->func = func;
+
+ notify->window_list = g_list_append( notify->window_list, (gpointer) wnd_data );
+
+}
+
+struct notify_priv* win32_gui_notify_new(struct datawindow_priv *parent)
+{
+ struct notify_priv* notify = g_new0(struct notify_priv,1);
+ notify->parent = parent;
+ return notify;
+}
+
+LRESULT CALLBACK message_handler(HWND hwnd, UINT win_message, WPARAM wParam, LPARAM lParam)
+{
+ enum message_id message = INVALID;
+ int param1 = -1;
+ int param2 = -1;
+ HWND hwndDlg = hwnd;
+
+ switch (win_message)
+ {
+ case WM_CREATE:
+ {
+ message = WINDOW_CREATE;
+ }
+ break;
+ case WM_SIZE:
+ {
+ message = WINDOW_SIZE;
+ param1 = LOWORD(lParam);
+ param2 = HIWORD(lParam);
+ }
+ break;
+ case WM_DESTROY:
+ {
+ message = WINDOW_DESTROY;
+ }
+ break;
+ case WM_NOTIFY:
+ {
+ hwndDlg = (((LPNMHDR)lParam)->hwndFrom);
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case NM_DBLCLK:
+ {
+ message = DBLCLICK;
+#ifdef LPNMITEMACTIVATE
+ param1 = ((LPNMITEMACTIVATE)lParam)->iItem;
+#endif
+ }
+ break;
+ case NM_CLICK:
+ message = CLICK;
+ break;
+ }
+ }
+ break;
+ case WM_COMMAND:
+ {
+ hwndDlg = (HWND)lParam;
+
+ switch (HIWORD(wParam))
+ {
+ case EN_CHANGE:
+ {
+ message = CHANGE;
+ }
+ break;
+ case BN_CLICKED:
+ {
+ message = BUTTON_CLICK;
+ }
+ break;
+ }
+ }
+ break;
+
+ default:
+ return DefWindowProc(hwnd, win_message, wParam, lParam);
+ }
+
+ struct notify_priv* notify_data = (struct notify_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
+
+ if ( message != INVALID && notify_data && notify_data->window_list )
+ {
+
+ GList* current_element = g_list_first(notify_data->window_list);
+
+
+ struct window_data* wnd_data = NULL;
+ while (current_element != NULL)
+ {
+ wnd_data = current_element->data;
+
+ if ( (wnd_data->hwnd == hwndDlg || wnd_data->hwnd == NULL) && message == wnd_data->message)
+ {
+ wnd_data->func(notify_data->parent, param1, param2);
+ }
+
+ current_element = g_list_next(current_element);
+ }
+ }
+ return FALSE;
+}
diff --git a/gui/win32/win32_gui_notify.h b/gui/win32/win32_gui_notify.h
new file mode 100644
index 00000000..7c791e15
--- /dev/null
+++ b/gui/win32/win32_gui_notify.h
@@ -0,0 +1,18 @@
+
+enum message_id
+{
+ WINDOW_CREATE,
+ WINDOW_SIZE,
+ WINDOW_DESTROY,
+ DBLCLICK,
+ CLICK,
+ CHANGE,
+ BUTTON_CLICK,
+ INVALID
+
+};
+
+struct datawindow_priv;
+struct notify_priv* win32_gui_notify_new();
+void win32_gui_notify(struct notify_priv* notify, HWND hwnd, int message_id, void(*func)(struct datawindow_priv *parent, int param1, int param2));
+LRESULT CALLBACK message_handler(HWND hwnd, UINT win_message, WPARAM wParam, LPARAM lParam);