IPMsg之TMsgApp类

TMsgApp类声明如下:

//ipmsgcmn.h/line1713
class TMsgApp : public TApp {
public:
    TMsgApp(HINSTANCE _hI, LPSTR _cmdLine, int _nCmdShow);
    virtual ~TMsgApp();

    virtual void    InitWindow(void);
};

(一)继承关系
1. TMsgApp类继承自TApp类
(二)构造函数
1. TMsgApp(HINSTANCE _hI, LPSTR _cmdLine, int _nCmdShow)

//ipmsg.cpp/line19
TMsgApp::TMsgApp(HINSTANCE _hI, LPSTR _cmdLine, int _nCmdShow) : TApp(_hI, _cmdLine, _nCmdShow)
{
    LoadLibrary("RICHED20.DLL");
    srand((UINT)Time());
    TLibInit_AdvAPI32();
    TLibInit_Crypt32();
    TLibInit_WinSock();
}

调用父类的构造函数,然后做3件事:
(1) 加载库RICHED20.DLL,这个动态链接库的作用是字符编辑器相关文件。LoadLibrary()函数的作用是载入指定的动态链接库,并将它映射到当前进程使用的地址空间。一旦载入,即可访问库内保存的资源。
(2) 以当前时间作为随机数的种子。
(3) 首先介绍一下三个模块:
advapi32.dll:advapi32.dll是一个高级API应用程序接口服务库的一部分,包含的函数与对象的安全性,注册表的操控以及事件日志。
crypt32.dll:是windows加密API应用程序接口模块.
Ws2_32.dll: windows socket编程相关的模块
程序将这三个模块中的库函数取出来,并初始化IPMsg项目自己的函数指针。
2. ~TMsgApp()

TMsgApp::~TMsgApp()
{
}

由此可见析构函数在本类中不做任何的事情,析构的过程要利用父类的析构函数来完成。
(二)成员变量

(三)成员函数
1. void TMsgApp::InitWindow(void)

//ipmsg.cpp/line32
void TMsgApp::InitWindow(void)
{
    HWND        hWnd;
    char        class_name[MAX_PATH_U8] = IPMSG_CLASS, *tok, *msg, *p;
    char        *class_ptr = NULL;
    ULONG       nicAddr = 0;
    int         port_no = atoi(cmdLine);
    BOOL        show_history = FALSE;
    enum Stat { ST_NORMAL, ST_TASKBARUI_MSG, ST_EXIT, ST_ERR } status = ST_NORMAL;
    int         taskbar_msg = 0;
    int         taskbar_cmd = 0;

    if (port_no == 0) port_no = IPMSG_DEFAULT_PORT;

    if ((tok = strchr(cmdLine, '/'))) {
        DWORD   exit_status = 0xffffffff;

        for (tok=separate_token(tok, ' ', &p); tok && *tok == '/';
                tok=separate_token(NULL, ' ', &p)) {
            if (stricmp(tok, "/NICLIST") == 0) {
                int         num = 0;
                AddrInfo    *addrs = GetIPAddrs(FALSE, &num);
                char        buf[8192] = "No NIC", *p = buf;

                for (int i=0; addrs && i < num; i++) {
                    p += sprintf(p, " NIC(%d) = %s\n", i+1, Tinet_ntoa(*(LPIN_ADDR)&addrs[i].addr));
                }
                MessageBox(0, buf, IP_MSG, MB_OK);
                delete [] addrs;
                status = ST_EXIT;
            }
            else if (stricmp(tok, "/NICID") == 0) { // NICID 指定
                status = ST_ERR;
                if ((tok = separate_token(NULL, ' ', &p))) {
                    int         target = atoi(tok) - 1;
                    int         num = 0;
                    AddrInfo    *addrs = GetIPAddrs(FALSE, &num);
                    if (addrs && target > 0 && target < num) {
                        nicAddr = addrs[target].addr;
                        status = ST_NORMAL;
                    }
                    delete [] addrs;
                }
                if (status == ST_ERR) break;
            }
            else if (stricmp(tok, "/NIC") == 0) {   // NIC 指定
                if (!(tok = separate_token(NULL, ' ', &p)) || !(nicAddr = ResolveAddr(tok))) {
                    status = ST_ERR;
                    break;
                }
            }
            else if (stricmp(tok, "/MSG") == 0) {   // コマンドラインモード
                MsgMng  msgMng(nicAddr, port_no);
                ULONG   command = IPMSG_SENDMSG|IPMSG_NOADDLISTOPT|IPMSG_NOLOGOPT, destAddr;
                status  = ST_EXIT;

                while ((tok = separate_token(NULL, ' ', &p)) && *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)) && (destAddr = ResolveAddr(tok))) {
                    exit_status = msgMng.Send(destAddr, Thtons(port_no), command, msg) ? 0 : -1;
                }
                else status = ST_ERR;
            }
            else if (stricmp(tok, "/SHOW_HISTORY") == 0) {  // インストーラからの起動
                show_history = TRUE;
            }
            else if (stricmp(tok, "/TASKBAR_MSG") == 0) {   // TaskbarUI用
                if (!(class_ptr = separate_token(NULL, ' ', &p))
                || !(tok = separate_token(NULL, ' ', &p))
                || !(taskbar_cmd = atoi(tok))
                || !(taskbar_msg = ::RegisterWindowMessage(IP_MSG))) {
                    status = ST_ERR;
                    break;
                }
                if ((hWnd = FindWindowU8(class_ptr))) {
                    ::PostMessage(hWnd, taskbar_msg, taskbar_cmd, 0);
                }
                ::ExitProcess(0xffffffff);
                return;
            }
            else status = ST_ERR;
        }
        if (status != ST_NORMAL) {
            if (status == ST_ERR) {
                MessageBox(0, IPMSG_USAGE, IP_MSG, MB_OK);
            }
            ::ExitProcess(exit_status);
            return;
        }
    }

    if (port_no != IPMSG_DEFAULT_PORT || nicAddr) {
        wsprintf(class_name, nicAddr ? "%s_%d_%s" : "%s_%d",
            IPMSG_CLASS, port_no, Tinet_ntoa(*(in_addr *)&nicAddr));
    }

    HANDLE  hMutex = ::CreateMutex(NULL, FALSE, class_name);
    ::WaitForSingleObject(hMutex, INFINITE);

    if ((hWnd = FindWindowU8(class_name)) ||
        !TRegisterClassU8(class_name, CS_DBLCLKS, ::LoadIcon(hI, (LPCSTR)IPMSG_ICON),
                        ::LoadCursor(NULL, IDC_ARROW))) {
        if (hWnd) ::SetForegroundWindow(hWnd);
        ::ExitProcess(0xffffffff);
        return;
    }

    mainWnd = new TMainWin(nicAddr, port_no);
    mainWnd->Create(class_name);
    ::ReleaseMutex(hMutex);
    ::CloseHandle(hMutex);

    if (show_history) mainWnd->SendMessage(WM_COMMAND, MENU_HELP_HISTORY, 0);
}

(1)定义HWND类型局部变量hWnd;
(2)定义char*类型局部变量class_name,tok,msg,p,class_ptr。初始化class_name为数组大小为MAX_PATH_U8 ,大小参看下面的代码段,内容为IPMSG_CLASS,参看下面的字符串。初始化class_ptr为空指针。

//tlib.h/line106
#define MAX_PATH_U8     (MAX_PATH * 3)
//minwindef.h/line60
//定义了编译器所支持的最长全路径名的长度
#define MAX_PATH          260
//ipmsg.cpp/line16
#define IPMSG_CLASS "ipmsg_class"

(3)初始化ULONG类型的nicaddr为0,表示的是IP地址的长整形值。
(4)根据父类的cmdLine值初始化int类型局部变量prot_no参数。这个值表示端口。
(5)定义变量show_history为FALSE;
(6)定义枚举类型变量status并初始化为ST_NORMAL,即0;
(7)定义并初始化int类型的taskbar_msg,taskbar_cmd为0;
(8)如果port_no从cmdline中没有取到值,那么就初始化为默认值 IPMSG_DEFAULT_PORT;

//ipmsg.h/line21
#define IPMSG_DEFAULT_PORT      0x0979

(9)如果cmdline变量中不包含任何的命令,即‘/’那么按照如下流程运行:
9.1 利用CreateMutex()函数创建互斥体,然后调用WaitForSingleObject()阻塞其他进程进入该互斥体,即系统中只能同时有一个进程进入该互斥体中运行。
9.2 查看是否有窗口类名为class_name的窗口正在运行,如果有的话hWnd的值为该窗口的句柄,否则的话为NULL 。
hWnd不为空,那么调用SetForegroundWindow函数将该函数将hWnd窗口的线程设置到前台,并且激活该窗口。然后从InitWindow函数退出,无返回值。
如果hWnd为空,那么就以class_name为窗口类名注册一个窗口,如果注册失败了就从InitWindow函数退出,无返回值。如果注册成功了,就接着运行9.3
9.3 定义一个TMainWin对象并且用父类的mainWnd指针成语指向它。
9.4 调用mainWnd指针指向对象的Create()函数。
9.5 释放互斥区
9.6 关闭句柄
9.7 如果show_history为真,那么就调用mainWnd指针指向TWin对象的sendMessage()函数。
9.8 InitWindow9()函数运行完毕。
10.如果在CmdLine中含有命令
这部分以后再分析,因为当前分析的是直接双击启动,而不是从命令行启动,所以cmdline都是空的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值