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函数,此 函数如下。易知函数主要调用两个函数,随后进入消息循环。

  1. int TApp::Run(void)
  2. {
  3. MSG     msg;
  4. InitApp();                      // 实现注册窗口类, 设置窗口处理过程
  5. InitWindow();                       // initWindow()在为一个纯虚函数,此处调用应该                                  // 是子类TMsgApp的initWindow()函数
  6. // 注意:由于是子类调用的父类的run成员函数
  7. // 而父类调用了一个纯虚函数,通过虚函数表,
  8. // 此调用为调用子类的initWindow函数。
  9. while (::GetMessage(&msg, NULL, 0, 0))
  10. {
  11. if (PreProcMsg(&msg))
  12. continue;
  13. ::TranslateMessage(&msg);
  14. ::DispatchMessage(&msg);
  15. }
  16. return  msg.wParam;
  17. }

下面看子类实现的initWindow()主要完成了什么功能:

下面是子类TMsgApp的initWindow函数

  1. void TMsgApp::InitWindow(void)
  2. {
  3. WNDCLASS    wc;
  4. HWND        hWnd;
  5. char        class_name[MAX_PATH] = IPMSG_CLASS, *tok, *msg, *p;
  6. ULONG       nicAddr = 0;
  7. int         port_no = atoi(cmdLine);
  8. if (port_no == 0)           、、端口处理,是否设置了端口
  9. port_no = IPMSG_DEFAULT_PORT;
  10. 、、处理命令行消息,如果是命令行方式启动
  11. if ((tok = strchr(cmdLine, '/')) && separate_token(tok, ' ', &p))
  12. {
  13. BOOL    diag = TRUE;
  14. DWORD   status = 0xffffffff;
  15. if (stricmp(tok, "/NIC") == 0)
  16. {
  17. if (tok = separate_token(NULL, ' ', &p))
  18. nicAddr = ResolveAddr(tok);
  19. }
  20. else if (stricmp(tok, "/MSG") == 0)
  21. {
  22. MsgMng  msgMng(nicAddr, port_no);
  23. ULONG   command = IPMSG_SENDMSG|IPMSG_NOADDLISTOPT|IPMSG_NOLOGOPT, destAddr;
  24. while ((tok = separate_token(NULL, ' ', &p)) != NULL && *tok == '/') {
  25. if (stricmp(tok, "/LOG") == 0)
  26. command &= ~IPMSG_NOLOGOPT;
  27. else if (stricmp(tok, "/SEAL") == 0)
  28. command |= IPMSG_SECRETOPT;
  29. }
  30. if ((msg = separate_token(NULL, 0, &p)) != NULL)
  31. {
  32. diag = FALSE;
  33. if ((destAddr = ResolveAddr(tok)) != NULL)
  34. status = msgMng.Send(destAddr, htons(port_no), command, msg) ? 0 : -1;
  35. }
  36. }
  37. 、、显示出错信息,给用户以提示。此种错误仅仅在命令行方式下产生
  38. if (nicAddr == 0)
  39. {
  40. if (diag)
  41. MessageBox(0, "ipmsg.exe [portno] [/MSG [/LOG] [/SEAL] <hostname or IP addr> <message>]/r/nipmsg.exe [portno] [/NIC nic_addr]", MSG_STR, MB_OK);
  42. ::ExitProcess(status);
  43. return;
  44. }
  45. }
  46. if (port_no != IPMSG_DEFAULT_PORT || nicAddr)
  47. wsprintf(class_name, nicAddr ? "%s_%d_%s" : "%s_%d", IPMSG_CLASS, port_no, inet_ntoa(*(in_addr *)&nicAddr));
  48. memset(&wc, 0, sizeof(wc));
  49. wc.style            = CS_DBLCLKS;
  50. wc.lpfnWndProc      = TApp::WinProc;        、、窗口处理函数为一个静态成员函数
  51. wc.cbClsExtra       = 0;
  52. wc.cbWndExtra       = 0;
  53. wc.hInstance        = hI;
  54. wc.hIcon            = ::LoadIcon(hI, (LPCSTR)IPMSG_ICON);
  55. wc.hCursor          = ::LoadCursor(NULL, IDC_ARROW);
  56. wc.hbrBackground    = NULL;
  57. wc.lpszMenuName     = NULL;
  58. wc.lpszClassName    = class_name;
  59. // 创建互斥mutex来保护共享资源,但是由于创建此mutex的线程不拥有其使用权。// WaitForSingleObject函数什么时候返回呢?
  60. HANDLE  hMutex = ::CreateMutex(NULL, FALSE, class_name);
  61. ::WaitForSingleObject(hMutex, INFINITE);
  62. if ((hWnd = ::FindWindow(class_name, NULL)) != NULL || ::RegisterClass(&wc) == 0)
  63. {
  64. if (hWnd != NULL)
  65. ::SetForegroundWindow(hWnd);
  66. ::ExitProcess(0xffffffff);
  67. return;
  68. }
  69. // 生成主窗口,并且将其显示
  70. mainWnd = new TMainWin(nicAddr, port_no);
  71. mainWnd->Create(class_name, IP_MSG, WS_OVERLAPPEDWINDOW | (IsNewShell() ? WS_MINIMIZE : 0));
  72. ::ReleaseMutex(hMutex);
  73. ::CloseHandle(hMutex);
  74. }

主程序的窗口处理过程为TApp类的一个静态成员函数,由此可知。回调函数可以封装在类中,但是注意必须作为类的静态成员函数。

  1. LRESULT CALLBACK TApp::WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2. {
  3. TWin *win = SearchWnd(hWnd);
  4. // 调用子类的窗口处理函数 由于其父类窗口处理过程定义的都为虚函数,而且基本没有对// 消息进行处理,因此主要在子类中实现消息处理过程,这就是调用虚函数的好处
  5. if (win)
  6. return  win->WinProc(uMsg, wParam, lParam);
  7. if ((win = preWnd) != NULL)
  8. {
  9. preWnd = NULL;
  10. AddWinByWnd(win, hWnd);
  11. return  win->WinProc(uMsg, wParam, lParam);
  12. }
  13. return  DefWindowProc(hWnd, uMsg, wParam, lParam);
  14. }

此程序将创建的所有的窗口句柄放到一个句柄数组中,以便查询。此窗口数组是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代码分析(二)相关推荐

  1. Android4.0图库Gallery2代码分析(二) 数据管理和数据加载

    Android4.0图库Gallery2代码分析(二) 数据管理和数据加载 2012-09-07 11:19 8152人阅读 评论(12) 收藏 举报 代码分析android相册优化工作 Androi ...

  2. IpMsg代码分析(一)

    IpMsg代码分析 (一) 以下部分参考自: http://www.vckbase.com/document/viewdoc/?id=1748 一.系统概述 IP Messenger是一款局域网内部聊 ...

  3. IpMsg代码分析(三)

    本次主要分析通信部分: Msgmng.cpp为通信处理部分的源文件,其中包括了几乎所有的socket通信代码. Class Msgmng为通信的管理类.构造函数如下: Line: 18 MsgMng: ...

  4. Linux-kernel网桥代码分析(二)

    第三部分: ioctl管理网桥 3.1 通过ioctl系统调用创建网桥      仍然以前的配置作为例,我们分用户空间程序brctl是如何通过ioctl系统调用在kernel空间内创建上述的数据结构. ...

  5. 水平集详解与代码分析二

    上一节我们分析了CV模型的原理并列出了演化公式,这一节我们将通过该公式编写CV模型的C++代码,代码调用了opencv库的一些函数,可以根据自己使用的版本更改.代码一一对应公式里的各项系数. 头文件. ...

  6. OSChina App代码分析二

    转载请标明出处: http://blog.csdn.net/zq2114522/article/details/50346073: 本文出自:[梁大盛的博客] 在第二篇里面我们首先分析OSChinaA ...

  7. 信息管理代码分析二读取二进制文件数据

    first和end做为全局变量,分别指向链表的头和尾.建立链表的方式也比较简易,从二进制文件数据块中,依次从头到尾读取,每读取一个就建立一个结点. /*基本模型*/ EMP *emp1; while( ...

  8. EOS智能合约开发系列(13): 多签合约代码分析(二)

    知识星球地址:https://t.zsxq.com/2zBaE6u 欢迎访问知识星球,并留言探讨.

  9. CP2K代码分析二:cp2k_run

    cp2k_runs cp2k_runs为CP2K主执行模块 #mermaid-svg-oBt60J8r5EXhCvPE .label{font-family:'trebuchet ms', verda ...

最新文章

  1. 2022-2028年中国相变蜡行业市场前瞻与投资战略规划分析报告
  2. [Asp.net]c#中的斜杠和反斜杠
  3. 腾讯清新云计算数据中心主体工程明年初竣工
  4. 异步接口同步返回_同步|异步
  5. 安卓入门系列-02创建一个项目
  6. SAP Kyma的environmment和SAP 云平台的Global Account
  7. Redis DeskTop Manager 使用教程
  8. 信息奥赛一本通(1100:金币)
  9. 第九章 Servlet工作原理解析
  10. 正确的初始化,在 Java 编程中至关重要!
  11. CCCC-GPLT L1-037. A除以B 团体程序设计天梯赛
  12. 滴滴工程师带你深入理解 HTTP通信细节
  13. WordPress 速度优化的完整指南
  14. linux系统下使用gcc编译C++程序出现XXX未定义的引用的处理
  15. 《Git与Github使用笔记》第12章 Pull Request的使用
  16. 三菱Q系列PLC项目资料 本系统采用三菱Q系列PLC,本系统中用到16个伺服电机
  17. 每日新闻丨人工智能应用红利兑现期正在到来;三星向华为供应可折叠OLED面板...
  18. 高校教室多媒体设备报修管理系统
  19. SQL中实用的小技巧
  20. 43、总建筑面积大于20000㎡的地下或半地下建筑的防火要求

热门文章

  1. 关于STL中的map用法
  2. html家电分类,电器有哪些种类?家用电器都有哪些类型?
  3. QT小项目Demo【附功能图及源码】
  4. Windows Subsystem for Linux (WSL) 重置 - 重装操作系统
  5. Latex行号问题,不连续、突然从1开始、部分行号消失
  6. Kaggle系列(一):Spaceship Titanic(太空飞船泰坦尼克)
  7. How to get ‘kernel config‘ when CONFIG_IKCONFIG is not set ? (Method)
  8. PowerPoint小技巧
  9. ios获取已安装的应用列表
  10. 于丹《论语心得》中唯一让我感动的地方