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函数里面的获得消息和派送消息了!
}
- IPMSG飞鸽传书4——App类
- IPMSG飞鸽传书2——关于对话框
- IPMSG飞鸽传书3——协议翻译
- IPMSG飞鸽传书3——协议翻译
- IPMSG飞鸽传书1——编译源代码的方法
- IPMSG飞鸽传书5——网络协议解析手记1
- IPMSG飞鸽传书5——网络协议解析手记2
- IPMSG飞鸽传书7——文件发送源码分析
- IPMSG飞鸽传书——编译源代码的方法
- IPMSG(飞鸽传书)协议翻译
- IPMSG(飞鸽传书)协议翻译
- IPMSG(飞鸽传书)协议翻译
- ipmsg飞鸽传书系统即时通讯
- 飞鸽传书管理软件-“ipmsg”
- java版IpMsg(飞鸽传书)
- IPMSG(飞鸽传书)协议翻译
- IPMSG(飞鸽传书)协议翻译
- IPMsg飞鸽传书网络协议
- Android 应用程序之间数据共享—ContentProvider
- Java JDBC编程总结
- IPMSG飞鸽传书1——编译源代码的方法
- IPMSG飞鸽传书2——关于对话框
- IPMSG飞鸽传书3——协议翻译
- IPMSG飞鸽传书4——App类
- IPMSG飞鸽传书5——网络协议解析手记1
- IPMSG飞鸽传书5——网络协议解析手记2
- IPMSG飞鸽传书6--文件传输解析
- IPMSG飞鸽传书7——文件发送源码分析
- Verilog 【以下的语句我基本没怎么懂,在上篇里。故记下,虽然没什么逻辑,但是可以帮助我再看下去】
- centos 和 ubuntu 下单网卡设置多个IP
- 一上午过去了。
- Android: 通过Runtime.getRuntime().exec调用底层Linux下的程序或脚本