www.pudn.com > emGUI.rar > window.c
/* * Window layer * * * COPYRIGHT (c) 2001 - 2010. * emTech System Corporation. * * The license and distribution terms for this file may be * found in found in the file LICENSE. */ /* Huangf emcore@263.net */ #include "emGUI.h" #include#include void WndInitialization() { } static void _SaveDrawArea( Window *win ) { void *memory = win->memory; void *drawarea = win->drawArea; SaveDrawArea( drawarea, memory, win->left, win->top, win->right, win->bottom ); } static void _RestoreDrawArea( Window *win ) { void *memory = win->memory; void *drawarea = win->drawArea; RestoreDrawArea( drawarea, memory, win->left, win->top, win->right, win->bottom ); } /* API */ WndID CreateWindow( AppID app, WndID parent, int mode, void *wndProc, int l, int t, int w, int h ) { Window *win; if (w <= 0 || h <= 0){ return NULL; } if (app == NULL){ return NULL; } if (mode < 0 || mode > WINMODE_MAX){ return NULL; } if (wndProc == NULL){ return NULL; } win =(struct Window *) malloc(sizeof(struct Window)); if (win == NULL) return NULL; memset(win, 0, sizeof(struct Window)); /* general information */ win->application = app; win->parent = parent; win->mode = mode; win->wndProc = wndProc; if (parent){ /* get absolute coord */ win->left = l + parent->left; win->top = t + parent->top; } else{ win->left = l; win->top = t; } win->right = win->left + w - 1; win->bottom = win->top + h - 1; /* make win is inside screen or inside its parent */ if (win->left < 0){ win->left = 0; } if (win->top < 0){ win->top = 0; } /* Check right & bottom here */ /* sun window list */ _Chain_Initialize_empty( &win->subWinList ); /* window drawing area */ if (parent == NULL){ switch(mode){ case MAINWND: win->memory = malloc(SysBytesPerScreen()); win->drawArea = win->memory; break; case SYSMODAL: case APPMODAL: if (_Chain_Is_empty(&app->WinList)){ /* no MAINWIN defined before this window, * not allowed in emGUI */ free(win); return NULL; } win->memory = malloc(CalcMemGCSize(win->left, win->top, w, h)); win->drawArea = ((Window *)(app->WinList.first))->drawArea; _SaveDrawArea(win); break; if (win->memory == NULL){ /* have not Insert into */ free(win); return NULL; } default: /* impossible */ free(win); return NULL; } } else{ win->mode = SUBWIN; win->memory = NULL; win->drawArea = parent->drawArea; } if (parent == NULL){ /* insert into application window list */ _Chain_Prepend_unprotected( &app->WinList, &win->node ); /* send a message to application */ PostAppMessage( app, WNDCREATE, 0, (unsigned32)win ); } else{ /* insert parent window list */ _Chain_Prepend_unprotected( &parent->subWinList, &win->node ); } return win; } void DestroyWindow( WndID win ) { if (win == NULL || win->application == NULL){ return; } /* Extract from window list, * may from parent window's subWndList or Application's WindList */ _Chain_Extract_unprotected( &win->node ); if (win->mode == MAINWND){ /* send WNDCLOSE to Application, so it will switch draw base */ PostAppMessage( win->application, WNDCLOSE, 0, (unsigned32)win ); } else if (win->mode == SUBWIN){ RECT rect = { win->left - win->parent->left, win->top - win->parent->top, win->right - win->parent->left, win->bottom - win->parent->top }; InvalidateRect( win->parent, &rect ); } else{ _RestoreDrawArea(win); } /* Post destroy message to current Window */ PostMessage( win, WNDDESTROY, 0, 0L ); } /* really destroy window, called by DefaultWndProc */ void _DestroyWindow( WndID win ) { if (win->memory){ free(win->memory); } free(win); } Window *FindWindow( Application *app, int x, int y ) { Window *win, *subwin; /* find window in current application to handle this event, * rember, only the first window & its subwindows is searched */ if (_Chain_Is_empty(&app->WinList)){ return NULL; } win = (Window *)app->WinList.first; while (win != (Window *)_Chain_Tail(&app->WinList)){ if (win->left <= x && win->right >= x && win->top <= y && win->bottom >=y){ goto findsubwin; } win = (Window *)win->node.next; } return NULL; findsubwin: if (_Chain_Is_empty(&win->subWinList)){ return win; } subwin = (Window *)win->subWinList.first; while (subwin != (Window *)_Chain_Tail(&win->subWinList)){ if (subwin->left <= x && subwin->right >= x && subwin->top <= y && subwin->bottom >=y){ win = subwin; goto findsubwin; } subwin = (Window *)subwin->node.next; } return win; } void HideWindow( WndID win ) { RECT rect; if (win == NULL || win->application == NULL) return; /* remove it from window list */ _Chain_Extract_unprotected( &win->node ); switch (win->mode){ case MAINWND: /* switch drawing area */ PostAppMessage( win->application, WM_HIDE, 0, 0L ); break; case SYSMODAL: case APPMODAL: /* how to restore memory */ _RestoreDrawArea(win); break; case SUBWIN: rect.left = win->left - win->parent->left; rect.top = win->top - win->parent->top; rect.right = win->right - win->parent->left; rect.bottom = win->bottom - win->parent->top; InvalidateRect( win->parent, &rect ); break; } } void ShowWindow( WndID win ) { if (win == NULL || win->application == NULL) return; if (win->parent){ _Chain_Prepend_unprotected( &win->parent->subWinList, &win->node ); } else{ _Chain_Prepend_unprotected( &win->application->WinList, &win->node ); } switch (win->mode){ case MAINWND: /* switch drawing area */ PostAppMessage( win->application, WM_SHOW, 0, 0L ); break; case SYSMODAL: case APPMODAL: /* how to save memory */ _SaveDrawArea(win); case SUBWIN: /* how to redraw window */ win->invalid_l = 0; win->invalid_t = 0; win->invalid_r = win->right - win->left; win->invalid_b = win->bottom - win->top; win->paint_count++; PostMessage( win, WM_PAINT, 0, 0L ); break; } } void InvalidateRect( WndID win, LPRECT lpRect ) { lpRect->left += win->left; lpRect->top += win->top; lpRect->right += win->left; lpRect->bottom += win->top; if (win->invalid_l > lpRect->left){ win->invalid_l = lpRect->left; } if (win->invalid_t > lpRect->top){ win->invalid_t = lpRect->top; } if (win->invalid_b < lpRect->bottom){ win->invalid_b = lpRect->bottom; } if (win->invalid_r < lpRect->right){ win->invalid_r = lpRect->right; } /* make invalidate rect is inside Window */ win->paint_count++; PostMessage( win, WM_PAINT, 0, 0L ); }