minigui代码分析
来源:互联网 发布:华为ife矩阵 编辑:程序博客网 时间:2024/05/17 15:20
1.线程模式:MiniGui-Threads
定义:_MGRM_THREADS运行在MiniGui-Threads上的程序可以在不同的线程中建立多个窗口,但所有的窗口在一个进程或地址空间中运行,传统意义上的嵌入式操作系统。
2.进程模式:MiniGui-Processes
定义:_MGRM_Processes或者定义_LITE_VERSION
MiniGui-Processes上每个程序是单独的进程,每个进程也可以建立多个窗口,并且实现了多进程窗口系统。适用于具有完整UNIX特性的嵌入式式系统。3.独立应用模式:MiniGui-Standalone
定义:_MGRM_STANDALONE 或者定义_LITE_VERSION和_STAND_ALONE
通过独立任务的方式运行,既不需要多进程支持也不需要多线程支持。二、数据结构
1.CreateMainWindow函数参数:PMAINWINCREATE pCreateInfo
结构体MAINWINCREATE 定义了被创建的窗口的位置、标题、类型等基本参数。实际上包含了创建窗口的UI风格和窗口处理函数两方面的内容。PMAINWINCREATE为指向该结构体的指针。
typedef struct _MAINWINCREATE{ DWORD dwStyle; //窗口风格 DWORD dwExStyle; //窗口的附加风格 const char* spCaption; //窗口的标题 HMENU hMenu; //附加在窗口上的菜单句柄 HCURSOR hCursor; //在窗口中所使用的鼠标光标句柄 HICON hIcon; //程序的图标句柄 HWND hHosting; //窗口消息队列的托管窗口 int (*MainWindowProc)(HWND, int, WPARAM, LPARAM); //该窗口的消息处理函数指针,回调函数 int lx, ty, rx, by; //窗口相对屏幕的绝对坐标,以象素点表示 int iBkColor; //窗口背景颜色 DWORD dwAddData; //附带给窗口的一个32 位值 DWORD dwReserved; //预留,没有用到}MAINWINCREATE;typedef MAINWINCREATE* PMAINWINCREATE;2.MAINWIN结构体:主窗口的详细信息由该结构体给出
typedef struct _MAINWIN{ /* These fields are similiar with CONTROL struct. */ unsigned char DataType; // 数据类型,表示是否是一个窗口(主窗口或者控件窗口),对于该结构和CONTROL结构,都必须是TYPE_HWND</span> unsigned char WinType; // 判断是否是主窗口,对于该结构,必须是TYPE_MAINWIN</span> unsigned short Flags; // special runtime flags, such EraseBkGnd flags int left, top; // the position and size of main window. int right, bottom; int cl, ct; // the position and size of client area. int cr, cb; DWORD dwStyle; // the styles of main window. DWORD dwExStyle; // the extended styles of main window. int iBkColor; // the background color. HMENU hMenu; // handle of menu. HACCEL hAccel; // handle of accelerator table. HCURSOR hCursor; // handle of cursor. HICON hIcon; // handle of icon. HMENU hSysMenu; // handle of system menu. PLOGFONT pLogFont; // pointer to logical font. char* spCaption; // the caption of main window. int id; // the identifier of main window. LFSCROLLBARINFO vscroll; // the vertical scroll bar information. LFSCROLLBARINFO hscroll; // the horizital scroll bar information. /** the window renderer */ WINDOW_ELEMENT_RENDERER* we_rdr; HDC privCDC; // the private client DC. INVRGN InvRgn; // 这个主窗口的无效区域,在处理MSG_PAINT消息时很重要 PGCRINFO pGCRInfo; // pointer to global clip region info struct. // the Z order node. int idx_znode; PCARETINFO pCaretInfo; // pointer to system caret info struct. DWORD dwAddData; // the additional data. DWORD dwAddData2; // the second addtional data. int (*MainWindowProc)(HWND, int, WPARAM, LPARAM); // the address of main window procedure. struct _MAINWIN* pMainWin; // the main window that contains this window. for main window, always be itself. HWND hParent; // the parent of this window. for main window, always be HWND_DESKTOP. /* Child windows.*/ HWND hFirstChild; // the handle of first child window. HWND hActiveChild; // the currently active child window. HWND hOldUnderPointer; // the old child window under pointer. HWND hPrimitive; // the premitive child of mouse event. NOTIFPROC NotifProc; // the notification callback procedure. /* window element data. */ struct _wnd_element_data* wed; /* Main Window hosting. The following members are only implemented for main window.*/ struct _MAINWIN* pHosting; // the hosting main window. struct _MAINWIN* pFirstHosted; // the first hosted main window. struct _MAINWIN* pNextHosted; // the next hosted main window. PMSGQUEUE pMessages; // the message queue. GCRINFO GCRInfo; // the global clip region info struct. put here to avoid invoking malloc function.#ifdef _MGRM_THREADS pthread_t th; // the thread which creates this main window.#endif//the controls as mainHWND hFirstChildAsMainWin; HDC secondaryDC; // the secondary window dc. ON_UPDATE_SECONDARYDC update_secdc; // the callback of secondary window dc RECT update_rc;} MAINWIN;3.MSGQUEUE消息队列
struct _MSGQUEUE{ DWORD dwState; // message queue states#ifdef _MGRM_THREADS pthread_mutex_t lock; // lock sem_t wait; // the semaphore for wait message sem_t sync_msg; // the semaphore for sync message#endif PQMSG pFirstNotifyMsg; // head of the notify message queue PQMSG pLastNotifyMsg; // tail of the notify message queue#ifdef _MGRM_THREADS PSYNCMSG pFirstSyncMsg; // head of the sync message queue PSYNCMSG pLastSyncMsg; // tail of the sync message queue#else IDLEHANDLER OnIdle; // Idle handler#endif#ifdef _MGRM_THREADS PMAINWIN pRootMainWin; // The root main window of this message queue.#endif MSG* msg; /* post message buffer */ int len; /* buffer len */ int readpos, writepos; /* positions for reading and writing */ int FirstTimerSlot; /* the first timer slot to be checked */ DWORD TimerMask; /* timer slots mask */ int loop_depth; /* message loop depth, for dialog boxes. */};三、CreateMainWindow函数流程
1.init_desktop_win
<pre name="code" class="objc">static void init_desktop_win (void){ static MAINWIN sg_desktop_win; PMAINWIN pDesktopWin; LICENSE_SET_MESSAGE_OFFSET(); pDesktopWin = &sg_desktop_win; //作为默认的Desktop pDesktopWin->pMessages = __mg_dsk_msg_queue; // 自己的消息队列,其他窗口发送的SendMessage将消息压入该队列[luther.gliethttp] pDesktopWin->MainWindowProc = DesktopWinProc; // 桌面默认回调处理函数 pDesktopWin->DataType = TYPE_HWND; pDesktopWin->WinType = TYPE_ROOTWIN;#ifdef _MGRM_THREADS pDesktopWin->th = __mg_desktop;#endif pDesktopWin->pLogFont = GetSystemFont (SYSLOGFONT_WCHAR_DEF); pDesktopWin->spCaption = "THE DESKTOP WINDOW"; pDesktopWin->pGCRInfo = &sg_ScrGCRInfo; pDesktopWin->idx_znode = 0; pDesktopWin->pMainWin = pDesktopWin; pDesktopWin->we_rdr = __mg_def_renderer; __mg_hwnd_desktop = (HWND)pDesktopWin; // 登记到desktop的全局量中 __mg_dsk_win = pDesktopWin;}2.main函数
#define main_entry main#define MiniGUIMain \MiniGUIAppMain (int args, const char* argv[]); \int main_entry (int args, const char* argv[]) \{ \ int iRet = 0; \ if (InitGUI (args, argv) != 0) { \ return 1; \ } \ iRet = MiniGUIAppMain (args, argv); \ TerminateGUI (iRet); \ return iRet; \} \int MiniGUIAppMain
3.CreateMainWindow函数流程
HWND GUIAPI CreateMainWindowEx (PMAINWINCREATE pCreateInfo, const char* werdr_name, const WINDOW_ELEMENT_ATTR* we_attrs, const char* window_name, const char* layer_name){ // 指针 PMAINWIN pWin; if (pCreateInfo == NULL) { return HWND_INVALID; } if (!(pWin = calloc(1, sizeof(MAINWIN)))) { //分配结构体内存 return HWND_INVALID; }#ifdef _MGRM_THREADS //这是重要部分,用于找到消息队列 if (pCreateInfo->hHosting == HWND_DESKTOP || pCreateInfo->hHosting == 0) { /*如果托管窗口为桌面窗口或者没有托管窗口,为新建的主窗口创建线程信息和消息队列,获取本线程关联的消息队列结构体。 *若获取失败说明该窗口是最顶层的主窗口,目前还有对应的消息队列,则为其创建一个消息队列结构体*/ if ((pWin->pMessages = GetMsgQueueThisThread ()) == NULL) { //试图获取本线程关联的消息队列结构体 if (!(pWin->pMessages = mg_InitMsgQueueThisThread ()) ) { //试图去创建一个消息队列结构体 free (pWin); return HWND_INVALID; } pWin->pMessages->pRootMainWin = pWin;//如果创建消息队列结构体成功,则设置当前窗口为根窗口 } else { /* Already have a top level main window, in case of user have set a wrong hosting window */ pWin->pHosting = pWin->pMessages->pRootMainWin;//设置托管口 } } else { pWin->pMessages = GetMsgQueueThisThread (); //直接获取,这种情况下,是可以肯定消息队列已经存在 if (pWin->pMessages != kernel_GetMsgQueue (pCreateInfo->hHosting) || //该函数的调用者必须和hosting的消息队列所在线程一致。这很重要 pWin->pMessages == NULL) { free (pWin); return HWND_INVALID; } } if (pWin->pHosting == NULL) //如果当前窗口的托管主窗口为空,利用传递的函数参数获得托管主窗口信息 pWin->pHosting = gui_GetMainWindowPtrOfControl (pCreateInfo->hHosting); /* leave the pHosting is NULL for the first window of this thread. */#else pWin->pHosting = gui_GetMainWindowPtrOfControl (pCreateInfo->hHosting); //运行模式为非MiniGui-Threads,获得托管窗口的句柄 if (pWin->pHosting == NULL) pWin->pHosting = __mg_dsk_win; //托管窗口句柄为空,设置托管窗口为默认桌面窗口 pWin->pMessages = __mg_dsk_msg_queue; //将消息队列设置为默认桌面消息队列#endif pWin->pMainWin = pWin; //以下部分在初始化结构体成员,可以忽略 pWin->hParent = 0; //当前窗口的父窗口不存在 pWin->pFirstHosted = NULL; //第一个托管主窗口 pWin->pNextHosted = NULL; //下一个托管主窗口 pWin->DataType = TYPE_HWND; //数据类型 pWin->WinType = TYPE_MAINWIN; //窗口类型#ifdef _MGRM_THREADS pWin->th = pthread_self(); //创建主窗口的线程#endif pWin->hFirstChild = 0; //第一个子窗口的句柄为0,即不存在 pWin->hActiveChild = 0; //当前活动的子窗口的句柄为0,即不存在 pWin->hOldUnderPointer = 0; //旧的子窗口 pWin->hPrimitive = 0; pWin->NotifProc = NULL; pWin->dwStyle = pCreateInfo->dwStyle; pWin->dwExStyle = pCreateInfo->dwExStyle;#ifdef _MGHAVE_MENU pWin->hMenu = pCreateInfo->hMenu;#else pWin->hMenu = 0;#endif pWin->hCursor = pCreateInfo->hCursor; pWin->hIcon = pCreateInfo->hIcon;#ifdef _MGHAVE_MENU if ((pWin->dwStyle & WS_CAPTION) && (pWin->dwStyle & WS_SYSMENU)) //如果当前窗口包含标题且包含系统菜单,则创建系统菜单 pWin->hSysMenu= CreateSystemMenu ((HWND)pWin, pWin->dwStyle); else#endif pWin->hSysMenu = 0; //否则系统菜单项为0 pWin->spCaption = FixStrAlloc (strlen (pCreateInfo->spCaption));//分配空间存放标题 if (pCreateInfo->spCaption [0]) //如果函数参数结构体的标题字符串的第一个字符非空 strcpy (pWin->spCaption, pCreateInfo->spCaption); //复制标题到结构体的标题项 pWin->MainWindowProc = pCreateInfo->MainWindowProc; //消息处理函数 pWin->iBkColor = pCreateInfo->iBkColor; pWin->pCaretInfo = NULL; //指向系统插入字符信息结构体 pWin->dwAddData = pCreateInfo->dwAddData; pWin->dwAddData2 = 0; pWin->secondaryDC = 0; /* Scroll bar */ //下面是初始化滚动条相关的内容 if (pWin->dwStyle & WS_VSCROLL) { //垂直方向的滚动条 pWin->vscroll.minPos = 0; pWin->vscroll.maxPos = 100; pWin->vscroll.curPos = 0; pWin->vscroll.pageStep = 101; pWin->vscroll.barStart = 0; pWin->vscroll.barLen = 10; pWin->vscroll.status = SBS_NORMAL; } else pWin->vscroll.status = SBS_HIDE | SBS_DISABLED; if (pWin->dwStyle & WS_HSCROLL) { //水平方向的滚动条 pWin->hscroll.minPos = 0; pWin->hscroll.maxPos = 100; pWin->hscroll.curPos = 0; pWin->hscroll.pageStep = 101; pWin->hscroll.barStart = 0; pWin->hscroll.barLen = 10; pWin->hscroll.status = SBS_NORMAL; } else pWin->hscroll.status = SBS_HIDE | SBS_DISABLED; /** perfer to use parent renderer */ //初始化渲染器相关的内容,这时可以忽略这一部分 if (pWin->dwExStyle & WS_EX_USEPARENTRDR) { if (((PMAINWIN)pCreateInfo->hHosting)->we_rdr) { pWin->we_rdr = ((PMAINWIN)pCreateInfo->hHosting)->we_rdr; ++pWin->we_rdr->refcount; } else { return HWND_INVALID; } } else { /** set window renderer */ set_window_renderer (pWin, werdr_name); } /** set window element data */ while (we_attrs && we_attrs->we_attr_id != -1) { // append_window_element_data (pWin, // we_attrs->we_attr_id, we_attrs->we_attr); DWORD _old; set_window_element_data ((HWND)pWin, we_attrs->we_attr_id, we_attrs->we_attr, &_old); ++we_attrs; } /** prefer to parent font */ if (pWin->dwExStyle & WS_EX_USEPARENTFONT) pWin->pLogFont = __mg_dsk_win->pLogFont; else { pWin->pLogFont = GetSystemFont (SYSLOGFONT_WCHAR_DEF); } if (SendMessage ((HWND)pWin, MSG_NCCREATE, 0, (LPARAM)pCreateInfo)) // MSG_NCCREATE表示窗口已经创建但是还没有向系统注册 goto err; /** reset menu size */ ResetMenuSize ((HWND)pWin);#ifdef __TARGET_FMSOFT__ pCreateInfo->lx += __mg_mainwin_offset_x; pCreateInfo->rx += __mg_mainwin_offset_x; pCreateInfo->ty += __mg_mainwin_offset_y; pCreateInfo->by += __mg_mainwin_offset_y;#endif SendMessage ((HWND)pWin, MSG_SIZECHANGING, //开始发生一些消息,让窗口进行一些工作 (WPARAM)&pCreateInfo->lx, (LPARAM)&pWin->left); SendMessage ((HWND)pWin, MSG_CHANGESIZE, (WPARAM)&pWin->left, 0); pWin->pGCRInfo = &pWin->GCRInfo; if (SendMessage (HWND_DESKTOP, MSG_ADDNEWMAINWIN, (WPARAM) pWin, 0) < 0)//这个很重要:把主窗口发送给Desktop窗口托管,进行管理。 goto err; /* * We should add the new main window in system and then * SendMessage MSG_CREATE for application to create * child windows. */ if (SendMessage ((HWND)pWin, MSG_CREATE, 0, (LPARAM)pCreateInfo)) { //发送一个MSG_CREATE消息,告知应用程序窗口已经创建成功 SendMessage(HWND_DESKTOP, MSG_REMOVEMAINWIN, (WPARAM)pWin, 0); goto err; }<pre name="code" class="objc">
#ifndef _MGRM_PROCESSES screensaver_create();#endif return (HWND)pWin;err:#ifdef _MGRM_THREADS if (pWin->pMessages && pWin->pHosting == NULL) { mg_FreeMsgQueueThisThread (); }#endif if (pWin->secondaryDC) DeleteSecondaryDC ((HWND)pWin); free (pWin); return HWND_INVALID;}
1)判断传入的参数pCreateInfo是否为空
Case NULL:若参数为空,返回HWND_INVALID
Case NOT NULL:若参数不为空,继续执行22)为PMAINWIN类型的pWin分配内存空间,并判断pWin是否为空
Case NULL:分配空间失败,返回HWND_INVALID
Case NOT NULL:分配空间成功,继续执行33)是否定义_MGRM_THREADS:
3.a定义了_MGRM_THREADS,代表minigui的运行模式为MiniGui-Threads
设置pWin的成员pWin->pMessages和pWin->pHosting3.b没有定义_MGRM_THREADS,代表minigui的运行模式为非MiniGui-Threads
设置pWin的成员pWin->pMessages和pWin->pHosting4)设置pWin的成员。
5)初始化渲染器相关的内容。
6)SendMessage ((HWND)pWin,MSG_NCCREATE, 0, (LPARAM)pCreateInfo)
表示该窗口已经创建但是还没有向系统进行注册,当收到这种类型的消息时可以对自己创建的对象进行初始化,但不能创建子窗口,也不能进行绘图。如果函数返回值为非零值,创建的窗口将被销毁。
7)SendMessage ((HWND)pWin, MSG_SIZECHANGING,(WPARAM)&pCreateInfo->lx, (LPARAM)&pWin->left);
指示了将要被更改的窗口的大小,当窗口大小将要发生改变时,该消息会发送给窗口。如果你想要控制窗口改变后的实际位置和大小(窗口改变可能是MoveWindow或者其他函数引起的),你需要使用MSG_SIZECHANGING作为SendMessage函数的第二个参数,并且通过第二个参数返回位置和大小信息。
9)SendMessage ((HWND)pWin,MSG_CHANGESIZE, (WPARAM)&pWin->left, 0);
确定改变后的窗口大小。
9)SendMessage (HWND_DESKTOP,MSG_ADDNEWMAINWIN, (WPARAM) pWin, 0);
把主窗口发送给Desktop窗口托管,进行管理,并绘制窗口。
10)SendMessage ((HWND)pWin,MSG_CREATE, 0, (LPARAM)pCreateInfo);
发送一个MSG_CREATE消息,告知应用程序窗口已经创建成功。
- minigui代码分析
- miniGUI实现进度条代码
- minigui 初始化分析
- MiniGUI原理分析
- MiniGUI原理分析GAL
- MiniGUI原理分析 控件
- MiniGUI 定时器分析
- MiniGUI源码分析
- minigui 初始化分析
- MiniGUI源码分析-- 开始篇
- MiniGUI
- MiniGUi
- minigui
- MiniGui
- MiniGUI源码分析——DC分析
- vxworks下的MINIGUI代码裁减记录
- 有关MiniGUI虚拟键盘实现的代码
- Minigui IAL引擎实现 分析 转
- error: only position independent executables (PIE) are supported.
- 网络层协议:IP(Internet Protocol)的分类与子网
- AutoTest--HTML/XML/XPath基础及辅助工具
- Maven学习(十一)----Maven深入学习(一)- 坐标
- 用于列出文件目录的java实用小程序,方便文件查找
- minigui代码分析
- 电脑同时安装两个版本java jdk
- Maven学习(十二)---Maven深入学习(二)- 依赖
- 输入两颗二叉树A,B,判断B是不是A的子结构
- Maven学习(十三)---Maven深入学习(三)- 聚合与继承
- 写给大一大二大三还在迷惘中的学生
- 回文数猜想
- SQL生成拼音首码
- Maven学习(十四)--Maven深入学习(四)- 知识总结