IPMSG飞鸽传书4——App类

经过几周的艰苦奋战,终于对飞鸽传书(以下简称FG)的架构有了一个简单的了解,下面分类分析一下各个类的基本情况。

    首先是App类。和MFC中其他程序一样,FG中存在着一个App类,用来发送消息,创建和管理窗口等。

main函数如下:

//这里是主函数!!!!!!!!!!!!!!!调用app的run开始执行

//构造函数中有initapp等操作

int WINAPI WinMain(HINSTANCE hI, HINSTANCE, LPSTR cmdLine, int nCmdShow)
{
//建立一个TMsgApp类的对象

TMsgApp app( hI, cmdLine, nCmdShow );

return app.Run();//run函数完成主要的工作,初始化窗口,循环获得和发送消息等
}

TMsgApp是TApp类的子类,TApp类的定义如下:

class TApp
{

protected:

//static的一大堆变量

static TWin    **wndArray;

static int    wndCnt;

static TWin    *SearchWnd(HWND hW);

static BOOL    SearchWndIndex(TWin *win, int *index);

static void    AddWinSub(TWin *win);

HINSTANCE    hCtl3d;

LPSTR     cmdLine;

int      nCmdShow;

//有一个TWin的mainwnd,指向TMainWin类创建的窗口

TWin     *mainWnd;

virtual BOOL   InitApp(void);//注意这里的InitApp是虚函数,子类可以重载它

public:

TApp(HINSTANCE _hI, LPSTR _cmdLine, int _nCmdShow);

virtual ~TApp();

virtual void   InitWindow() = 0;

virtual int    Run();

static BOOL   PreProcMsg(MSG *msg);

 

static TWin    *preWnd;

static char    *defaultClass;

static HINSTANCE hI;

static void    AddWin(TWin *win);

static void    AddWinByWnd(TWin *win, HWND hWnd);

static void    DelWin(TWin *win);

static LRESULT CALLBACK WinProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
};

实现文件如下:

static char *tapp_id =
"@(#)Copyright (C) H.Shirouzu 1996-2001   tapp.cpp Ver0.95";

#include "tlib.h"

TWin**   TApp::wndArray   = NULL;

int    TApp::wndCnt   = 0;

TWin*   TApp::preWnd   = NULL;

HINSTANCE TApp::hI    = NULL;

char*   TApp::defaultClass = "tapp";

HINSTANCE LoadCtl3d(void);

 

TApp::TApp(HINSTANCE _hI, LPSTR _cmdLine, int _nCmdShow)
{
hI    = _hI;

cmdLine   = _cmdLine;

nCmdShow = _nCmdShow;

mainWnd   = NULL;

::CoInitialize(NULL);

hCtl3d = LoadCtl3d();

::InitCommonControls();
}

TApp::~TApp()
{
//删除TWin的主窗口指针,注意new是在initApp中new的!!!!!!!!!

delete mainWnd;

 

if ( hCtl3d )
{
   ::FreeLibrary(hCtl3d);
}

 

::CoUninitialize();
}

int TApp::Run(void)
{
MSG   msg;

InitApp();

InitWindow();//这里是纯虚拟构造函数!!!


while ( ::GetMessage(&msg, NULL, 0, 0) )
{
   if ( PreProcMsg(&msg) )
   {
    continue;
   }

   ::TranslateMessage(&msg);

   ::DispatchMessage(&msg);
}

return msg.wParam;
}

BOOL TApp::PreProcMsg(MSG *msg) // for TranslateAccel & IsDialogMessage
{

for ( HWND hWnd = msg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd) )
{
   //在WndArray中找到hWnd标志的那个TWin*并将之返回

   TWin *win = SearchWnd(hWnd);

   if ( win != NULL )
   {
    return win->PreProcMsg(msg);
   }
}

return FALSE;
}

//WNDCLASS窗口类的消息处理函数居然交给TApp的WinProc处理!!!

 

LRESULT CALLBACK TApp::WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//查找hWnd这个窗口,如果找到了,则调用win窗口的WinProc来处理

TWin *win = SearchWnd( hWnd );

if ( win ) // 找到了,不是第一次加入
{
   return win->WinProc(uMsg, wParam, lParam);
}

//是第一次加入,则加入wndarray

//如果是第一次调用TApp::WinProc则加入一个TWin到TWinArray,

//把PreWnd设置为NULL,然后创建一个TWin,

//然后把窗口hWnd赋给win的pWnd,然后调用Win的winproc处理

if ( ( win = preWnd ) != NULL )
{
   preWnd = NULL;//把preWnd设置为NULL,以后要用到
  
   //注意win不是NULL!win保存了prewnd原来的值

   //这里的hWnd已经create完毕,可以加入到hwndarray中了

   AddWinByWnd(win, hWnd);//把hWnd加入array中

   //掉用win的WinProc来处理

   return win->WinProc(uMsg, wParam, lParam);
}

return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

void TApp::AddWin( TWin *win )
{
// 仅仅只是把preWnd指向了win

preWnd = win;
}

//把TWin指针的hWnd设置为参数hWnd,然后加入到wndArray中

void TApp::AddWinByWnd(TWin *win, HWND hWnd)
{
win->hWnd = hWnd;

AddWinSub(win);
}

//在wndArray中加入TWin指针 win

void TApp::AddWinSub(TWin *win)
{

if ( SearchWnd ( win->hWnd ) != NULL )
{
   return;
}

#define BIG_ALLOC 100

TWin **_wndArray = wndArray;

if ( ( wndCnt % BIG_ALLOC ) == 0 )
{
   _wndArray = (TWin **)realloc(wndArray, sizeof(TWin *)
    * (wndCnt + BIG_ALLOC));
}

if ( _wndArray == NULL ) // 重新分配空间失败,直接返回
{
   return;
}

(wndArray = _wndArray)[wndCnt++] = win;

return;
}

//在wndArray中删除win指定的TWin窗口

void TApp::DelWin(TWin *win)
{

int   index;

if ( SearchWndIndex(win, &index) == FALSE )
{
   if ( preWnd == win )
   {
    preWnd = NULL;
   }

   return;
}

//TWin在TWinArray中存在

// 删除wndArray+index指向的那个指针,后面的所有TWin指针向前移动一格

memmove(wndArray + index, wndArray + index + 1,
   sizeof(TWin *) * ( --wndCnt - index ) );

// wndArray = (TWin **)realloc(wndArray, sizeof(TWin *) * wndCnt);
}

BOOL TApp::InitApp(void) // reference kwc
{

WNDCLASS wc;

memset( &wc, 0, sizeof(wc) );

wc.style    = (CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_DBLCLKS);

wc.lpfnWndProc   = WinProc;

wc.cbClsExtra    = 0;

wc.cbWndExtra   = 0;

wc.hInstance   = hI;

wc.hIcon    = NULL;

wc.hCursor    = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = NULL;

wc.lpszMenuName   = NULL;

wc.lpszClassName = defaultClass;// == "Tapp"

if ( ::FindWindow(defaultClass, NULL) == NULL )
{
   if ( ::RegisterClass(&wc) == 0 )
   {
    return FALSE;
   }
}

return TRUE;
}

TWin* TApp::SearchWnd(HWND hWnd) //在wndArray中查找hwnd是参数hWnd的TWin指针
{

for ( int cnt = 0; cnt < wndCnt; cnt++ )
{
   if ( wndArray[cnt]->hWnd == hWnd )
   {
    return wndArray[cnt];
   }
}

return NULL;
}

//找到TWin win指针的index

BOOL TApp::SearchWndIndex(TWin *win, int *index)
{

for ( *index = 0; *index < wndCnt; (*index) ++ )
{
   if ( wndArray[*index] == win )
   {
    return TRUE;
   }
}

return FALSE;
}

#if 0

IsXpManifest(void)
{
static BOOL done = FALSE;

static BOOL isXpManifest = FALSE;

//只查找一次,如果已经完成了查找,直接返回结果isXpManifest

if ( done )
{
   return isXpManifest;
}

//是第一次判断

done = TRUE;

HMODULE   hComctl;

char   path[MAX_PATH];

if ( ( hComctl = ::GetModuleHandle("comctl32")) == NULL )
{
   return isXpManifest = FALSE;
}

if ( ::GetModuleFileName(hComctl, path, sizeof(path)) == 0 )
{
   return isXpManifest = FALSE;
}


GetFileVersionInfo();

VerQueryValue();

}
#endif

HINSTANCE LoadCtl3d(void)
{
if ( IsNewShell() )
{
   return NULL;
}

HINSTANCE hCtl3d;

BOOL (WINAPI *Ctl3dRegister)(HANDLE);

BOOL (WINAPI *Ctl3dAutoSubclass)(HANDLE);

hCtl3d = ::LoadLibrary("ctl3d32.dll");

 

Ctl3dRegister = (BOOL (WINAPI *)(HANDLE))::GetProcAddress(hCtl3d, "Ctl3dRegister");

Ctl3dAutoSubclass = (BOOL (WINAPI *)(HANDLE))::GetProcAddress(hCtl3d, "Ctl3dAutoSubclass");

if ( Ctl3dRegister && Ctl3dAutoSubclass )
{
   Ctl3dRegister(TApp::hI);

   Ctl3dAutoSubclass(TApp::hI);
}

return hCtl3d;
}

其中TMsgApp的代码如下:

class TMsgApp : public TApp
{

public:

TMsgApp(HINSTANCE _hI, LPSTR _cmdLine, int _nCmdShow);

virtual ~TMsgApp();


virtual void InitWindow(void);
};

实现文件如下:

static char *ipmsg_id =
"@(#)Copyright (C) H.Shirouzu 1996-2002   ipmsg.cpp Ver2.00";

#include <time.h>
#include "tlib.h"
#include "resource.h"
#include "ipmsg.h"

#define IPMSG_CLASS "ipmsg_class"

TMsgApp::TMsgApp(HINSTANCE _hI, LPSTR _cmdLine, int _nCmdShow)
: TApp(_hI, _cmdLine, _nCmdShow)
{
//为后面的随机数做好准备

srand( (UINT)Time() );
}

TMsgApp::~TMsgApp()
{
}

void TMsgApp::InitWindow(void)
{
//注册一个窗口结构wc

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 )//命令行中没有设置端口号,则设置为默认的端口号
{
   //#define IPMSG_DEFAULT_PORT   0x0979

   port_no = IPMSG_DEFAULT_PORT;
}

//解析命令行,由于这里没有命令行,所以这个if tok 里面的语句不会执行

if ( ( tok = strchr(cmdLine, '/')) && separate_token(tok, ' ', &p) )
{
   BOOL diag = TRUE;

   DWORD status = 0xffffffff;

   if ( stricmp(tok, "/NIC") == 0 ) // NIC
   {
    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;
   }
}

//如果port_no不是默认的端口才这样做class_name=“ipmsg_class_0X979”

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) );
}

//建立WNDCLASS结构

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;

 

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

::WaitForSingleObject( hMutex, INFINITE );

//如果class_name名字的window已经存在了,则不创建新的程序,否则登记一下

//防止同时运行两个飞鸽!!

if ( ( hWnd = ::FindWindow( class_name, NULL ) ) != NULL
     || ::RegisterClass(&wc) == 0 )
{
   if ( hWnd != NULL )//找到了飞鸽,把飞鸽设置为前台程序
   {
    ::SetForegroundWindow(hWnd);
   }

   ::ExitProcess(0xffffffff);

   return;
}

//创建一个新的TMainWin窗口,这里的参数nicAddr为0,port_no为0X979

//这里创建各个管理类对象和常用到的各个窗口,创建udp socket 和tcpsocket

mainWnd = new TMainWin( nicAddr, port_no );

//创建TMainWin的CWnd窗口,启动时最小化

mainWnd->Create( class_name, IP_MSG, WS_OVERLAPPEDWINDOW |
   ( IsNewShell() ? WS_MINIMIZE : 0 ) );

//释放全局的hMutex变量

::ReleaseMutex(hMutex);

::CloseHandle(hMutex);

//InitApp完毕后进入Run函数里面的获得消息和派送消息了!
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值