IPMSG飞鸽传书4——App类

来源:互联网 发布:400选号平台 源码 编辑:程序博客网 时间:2024/05/17 21:20

经过几周的艰苦奋战,终于对飞鸽传书(以下简称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);

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

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

class TApp
{

protected:

//static的一大堆变量

staticTWin   **wndArray;

staticint   wndCnt;

staticTWin   *SearchWnd(HWND hW);

staticBOOL   SearchWndIndex(TWin *win, int *index);

staticvoid   AddWinSub(TWin *win);

HINSTANCE   hCtl3d;

LPSTR    cmdLine;

int     nCmdShow;

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

TWin    *mainWnd;

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

public:

TApp(HINSTANCE _hI, LPSTR _cmdLine, int_nCmdShow);

virtual ~TApp();

virtualvoid   InitWindow() =0;

virtualint   Run();

staticBOOL   PreProcMsg(MSG*msg);

 

staticTWin   *preWnd;

staticchar   *defaultClass;

static HINSTANCE hI;

staticvoid   AddWin(TWin *win);

staticvoid   AddWinByWnd(TWin *win, HWND hWnd);

staticvoid   DelWin(TWin *win);

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

实现文件如下:

static char *tapp_id =
"@(#)Copyright (C) H.Shirouzu1996-2001   tapp.cppVer0.95";

#include "tlib.h"

TWin**  TApp::wndArray   =NULL;

int   TApp::wndCnt   = 0;

TWin*  TApp::preWnd   = NULL;

HINSTANCETApp::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) // forTranslateAccel & IsDialogMessage
{

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

  TWin *win = SearchWnd(hWnd);

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

return FALSE;
}

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

 

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

TWin *win = SearchWnd( hWnd);

if ( win ) // 找到了,不是第一次加入
{
   returnwin->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, HWNDhWnd)
{
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) // referencekwc
{

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

return TRUE;
}

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

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

return NULL;
}

//找到TWin win指针的index

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

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

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.Shirouzu1996-2002   ipmsg.cppVer2.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)//命令行中没有设置端口号,则设置为默认的端口号
{
   //#defineIPMSG_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 ) //
   {
    MsgMngmsgMng(nicAddr, port_no);

    ULONGcommand = 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函数里面的获得消息和派送消息了!
}

原创粉丝点击