IpMsg代码分析(二)
Ipmsg.cpp为其主要的实现文件,其中调用系统的
int WINAPI WinMain(HINSTANCE hI, HINSTANCE, LPSTR cmdLine, int nCmdShow)作为入口函数,在函数中只是简单的调用了自己写的app类
TMsgApp app(hI, cmdLine, nCmdShow); // 调用其构造函数 创建对象
return app.Run(); // 由于TMsgApp没有自己的run
// 因此会调用其父类TApp的Run // 函数
在TMsgApp的构造函数的实现中,种下随机数字种子,只调用了一个系统函数
srand((UINT)Time());
TMsgApp 简单地public继承自TApp
在其继承中,添加了一个自己的函数virtual void InitWindow(void);
// 系统启动的时候调用的是其父类TApp的Run函数,此 函数如下。易知函数主要调用两个函数,随后进入消息循环。
- int TApp::Run(void)
- {
- MSG msg;
- InitApp(); // 实现注册窗口类, 设置窗口处理过程
- InitWindow(); // initWindow()在为一个纯虚函数,此处调用应该 // 是子类TMsgApp的initWindow()函数
- // 注意:由于是子类调用的父类的run成员函数
- // 而父类调用了一个纯虚函数,通过虚函数表,
- // 此调用为调用子类的initWindow函数。
- while (::GetMessage(&msg, NULL, 0, 0))
- {
- if (PreProcMsg(&msg))
- continue;
- ::TranslateMessage(&msg);
- ::DispatchMessage(&msg);
- }
- return msg.wParam;
- }
下面看子类实现的initWindow()主要完成了什么功能:
下面是子类TMsgApp的initWindow函数
- void TMsgApp::InitWindow(void)
- {
- WNDCLASS wc;
- HWND hWnd;
- char class_name[MAX_PATH] = IPMSG_CLASS, *tok, *msg, *p;
- ULONG nicAddr = 0;
- int port_no = atoi(cmdLine);
- if (port_no == 0) 、、端口处理,是否设置了端口
- port_no = IPMSG_DEFAULT_PORT;
- 、、处理命令行消息,如果是命令行方式启动
- if ((tok = strchr(cmdLine, '/')) && separate_token(tok, ' ', &p))
- {
- BOOL diag = TRUE;
- DWORD status = 0xffffffff;
- if (stricmp(tok, "/NIC") == 0)
- {
- if (tok = separate_token(NULL, ' ', &p))
- nicAddr = ResolveAddr(tok);
- }
- else if (stricmp(tok, "/MSG") == 0)
- {
- MsgMng msgMng(nicAddr, port_no);
- ULONG command = IPMSG_SENDMSG|IPMSG_NOADDLISTOPT|IPMSG_NOLOGOPT, destAddr;
- while ((tok = separate_token(NULL, ' ', &p)) != NULL && *tok == '/') {
- if (stricmp(tok, "/LOG") == 0)
- command &= ~IPMSG_NOLOGOPT;
- else if (stricmp(tok, "/SEAL") == 0)
- command |= IPMSG_SECRETOPT;
- }
- if ((msg = separate_token(NULL, 0, &p)) != NULL)
- {
- diag = FALSE;
- if ((destAddr = ResolveAddr(tok)) != NULL)
- status = msgMng.Send(destAddr, htons(port_no), command, msg) ? 0 : -1;
- }
- }
- 、、显示出错信息,给用户以提示。此种错误仅仅在命令行方式下产生
- if (nicAddr == 0)
- {
- if (diag)
- MessageBox(0, "ipmsg.exe [portno] [/MSG [/LOG] [/SEAL] <hostname or IP addr> <message>]/r/nipmsg.exe [portno] [/NIC nic_addr]", MSG_STR, MB_OK);
- ::ExitProcess(status);
- return;
- }
- }
- if (port_no != IPMSG_DEFAULT_PORT || nicAddr)
- wsprintf(class_name, nicAddr ? "%s_%d_%s" : "%s_%d", IPMSG_CLASS, port_no, inet_ntoa(*(in_addr *)&nicAddr));
- memset(&wc, 0, sizeof(wc));
- wc.style = CS_DBLCLKS;
- wc.lpfnWndProc = TApp::WinProc; 、、窗口处理函数为一个静态成员函数
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hI;
- wc.hIcon = ::LoadIcon(hI, (LPCSTR)IPMSG_ICON);
- wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
- wc.hbrBackground = NULL;
- wc.lpszMenuName = NULL;
- wc.lpszClassName = class_name;
- // 创建互斥mutex来保护共享资源,但是由于创建此mutex的线程不拥有其使用权。// WaitForSingleObject函数什么时候返回呢?
- HANDLE hMutex = ::CreateMutex(NULL, FALSE, class_name);
- ::WaitForSingleObject(hMutex, INFINITE);
- if ((hWnd = ::FindWindow(class_name, NULL)) != NULL || ::RegisterClass(&wc) == 0)
- {
- if (hWnd != NULL)
- ::SetForegroundWindow(hWnd);
- ::ExitProcess(0xffffffff);
- return;
- }
- // 生成主窗口,并且将其显示
- mainWnd = new TMainWin(nicAddr, port_no);
- mainWnd->Create(class_name, IP_MSG, WS_OVERLAPPEDWINDOW | (IsNewShell() ? WS_MINIMIZE : 0));
- ::ReleaseMutex(hMutex);
- ::CloseHandle(hMutex);
- }
主程序的窗口处理过程为TApp类的一个静态成员函数,由此可知。回调函数可以封装在类中,但是注意必须作为类的静态成员函数。
- LRESULT CALLBACK TApp::WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- TWin *win = SearchWnd(hWnd);
- // 调用子类的窗口处理函数 由于其父类窗口处理过程定义的都为虚函数,而且基本没有对// 消息进行处理,因此主要在子类中实现消息处理过程,这就是调用虚函数的好处
- if (win)
- return win->WinProc(uMsg, wParam, lParam);
- if ((win = preWnd) != NULL)
- {
- preWnd = NULL;
- AddWinByWnd(win, hWnd);
- return win->WinProc(uMsg, wParam, lParam);
- }
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- }
此程序将创建的所有的窗口句柄放到一个句柄数组中,以便查询。此窗口数组是TWin的静态数据成员。此静态成员变量操作了静态成员函数
如果找到了接受消息的窗口句柄,调用窗口句柄的消息处理函数进行处理
LRESULT TWin::WinProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
此窗口处理过程处理以下消息:
WM_CREATE、WM_CLOSE、WM_COMMAND、WM_SYSCOMMAND、WM_TIMER、WM_NCDESTROY、WM_QUERYENDSESSION、WM_ENDSESSION、WM_QUERYOPENWM_PAINT、WM_NCPAINT、WM_SIZE、WM_GETMINMAXINFO、WM_SETCURSOR、WM_MOUSEMOVE、WM_NCHITTEST、
WM_MEASUREITEM、WM_DRAWITEM、WM_NOTIFY、WM_CONTEXTMENU、WM_HOTKEY、WM_VSCROLL
此语句作用:如果done为真,即消息已经被处理,返回result,否则调用默认消息处理函数。
return done ? result : DefWindowProc(uMsg, wParam, lParam);
下面主要完成对TMainWin类中函数的分析,此函数中完成发送到此窗口的消息的处理。
例如TWin中成员函数WinProc调用了函数EvCreate();
由于在父类和子类中都存在EvCreate()函数。用基类的指针调用函数的时候,基类指针得到对象类型的确定化。调用父类中的WinProc函数(子类中没有对此函数进行重载),在WinProc函数中调用EvCreate(),此时应该调用子类的EvCreate()函数。可以理解为在调用函数的时候始终存在this指针,根据this指针指向的类型和类型中的成员函数是否是虚函数,是否重新定义来确定到底调用哪一个函数。
分析EvTimer函数处理过程。
此函数处理定时器消息。根据TimeID的不同分别进行处理
取得在线列表,是udp方式发送一个广播,此局域网中所有用户都可以接受到此消息,由于此消息有特定的格式,标识符等信息,由于是对特定端口进行的广播,故此局域网是哪个的所有用户都可以接受到此消息。
未完待续。。。
IpMsg代码分析(二)相关推荐
- Android4.0图库Gallery2代码分析(二) 数据管理和数据加载
Android4.0图库Gallery2代码分析(二) 数据管理和数据加载 2012-09-07 11:19 8152人阅读 评论(12) 收藏 举报 代码分析android相册优化工作 Androi ...
- IpMsg代码分析(一)
IpMsg代码分析 (一) 以下部分参考自: http://www.vckbase.com/document/viewdoc/?id=1748 一.系统概述 IP Messenger是一款局域网内部聊 ...
- IpMsg代码分析(三)
本次主要分析通信部分: Msgmng.cpp为通信处理部分的源文件,其中包括了几乎所有的socket通信代码. Class Msgmng为通信的管理类.构造函数如下: Line: 18 MsgMng: ...
- Linux-kernel网桥代码分析(二)
第三部分: ioctl管理网桥 3.1 通过ioctl系统调用创建网桥 仍然以前的配置作为例,我们分用户空间程序brctl是如何通过ioctl系统调用在kernel空间内创建上述的数据结构. ...
- 水平集详解与代码分析二
上一节我们分析了CV模型的原理并列出了演化公式,这一节我们将通过该公式编写CV模型的C++代码,代码调用了opencv库的一些函数,可以根据自己使用的版本更改.代码一一对应公式里的各项系数. 头文件. ...
- OSChina App代码分析二
转载请标明出处: http://blog.csdn.net/zq2114522/article/details/50346073: 本文出自:[梁大盛的博客] 在第二篇里面我们首先分析OSChinaA ...
- 信息管理代码分析二读取二进制文件数据
first和end做为全局变量,分别指向链表的头和尾.建立链表的方式也比较简易,从二进制文件数据块中,依次从头到尾读取,每读取一个就建立一个结点. /*基本模型*/ EMP *emp1; while( ...
- EOS智能合约开发系列(13): 多签合约代码分析(二)
知识星球地址:https://t.zsxq.com/2zBaE6u 欢迎访问知识星球,并留言探讨.
- CP2K代码分析二:cp2k_run
cp2k_runs cp2k_runs为CP2K主执行模块 #mermaid-svg-oBt60J8r5EXhCvPE .label{font-family:'trebuchet ms', verda ...
最新文章
- 2022-2028年中国相变蜡行业市场前瞻与投资战略规划分析报告
- [Asp.net]c#中的斜杠和反斜杠
- 腾讯清新云计算数据中心主体工程明年初竣工
- 异步接口同步返回_同步|异步
- 安卓入门系列-02创建一个项目
- SAP Kyma的environmment和SAP 云平台的Global Account
- Redis DeskTop Manager 使用教程
- 信息奥赛一本通(1100:金币)
- 第九章 Servlet工作原理解析
- 正确的初始化,在 Java 编程中至关重要!
- CCCC-GPLT L1-037. A除以B 团体程序设计天梯赛
- 滴滴工程师带你深入理解 HTTP通信细节
- WordPress 速度优化的完整指南
- linux系统下使用gcc编译C++程序出现XXX未定义的引用的处理
- 《Git与Github使用笔记》第12章 Pull Request的使用
- 三菱Q系列PLC项目资料 本系统采用三菱Q系列PLC,本系统中用到16个伺服电机
- 每日新闻丨人工智能应用红利兑现期正在到来;三星向华为供应可折叠OLED面板...
- 高校教室多媒体设备报修管理系统
- SQL中实用的小技巧
- 43、总建筑面积大于20000㎡的地下或半地下建筑的防火要求
热门文章
- 关于STL中的map用法
- html家电分类,电器有哪些种类?家用电器都有哪些类型?
- QT小项目Demo【附功能图及源码】
- Windows Subsystem for Linux (WSL) 重置 - 重装操作系统
- Latex行号问题,不连续、突然从1开始、部分行号消失
- Kaggle系列(一):Spaceship Titanic(太空飞船泰坦尼克)
- How to get ‘kernel config‘ when CONFIG_IKCONFIG is not set ? (Method)
- PowerPoint小技巧
- ios获取已安装的应用列表
- 于丹《论语心得》中唯一让我感动的地方