“星魔”回忆录【1】

想写一个做“星魔”的整个过程。。算是回忆录吧。呵呵。。把用到的细小技术和点点滴滴全都写出来。。也许技术含量不算高。。希望对一些人有用吧。。

一.界面设计

点击右键弹出菜单。。没有菜单栏。。觉得这样比较简洁。。

建立MFC框架的对话框。。设计上图这样。。

我命名工程名为“Client_”,在CClient_App类中的InitInstance()方法中完成几个任务:

类成员函数及变量

void InitCreateFile(CString cs_filename,int cs_resource,CString ResourceType);



HMODULE hmdl;

1.只允许一个实例运行。

HANDLE hdMutex=CreateMutex(NULL,TRUE,CLIENTMUTEXNAME);

if(NULL!=hdMutex)

{

   if(GetLastError()==ERROR_ALREADY_EXISTS)

   {

    AfxMessageBox(“已有一个程序实例在运行”);

    return TRUE;

   }

}

2.释放临时文件

释放皮肤需要的DLL文件及启动画面的swf文件

3.皮肤设置

调用皮肤所需要的函数

在ExitInstance() 中释放动态链接库及删除临时文件

至此,CClient_App类中的工作即完成。

二.主对话框的操作

下面开始CClient_Dlg对话框中的工作

1.点监听的时候。开启一个线程用于监听服务端的连接。。在InitDialog重载函数中开启一个心跳线程。。每隔一定时间遍历CListCtrl并发送数据包。来判断服务端是否在线。如果不在线则把它从CListCtrl中删除

2.在初始化对话框的时候同时进行socket初始化

WORD ver=MAKEWORD(2,2);      //初始化

WSAStartup(ver,&wsadata);

任务栏的气泡提示

nf.cbSize = (DWORD)sizeof(NOTIFYICONDATA);

nf.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP|NIF_INFO ;

nf.dwInfoFlags=NIIF_INFO;

nf.hWnd=this->m_hWnd;

nf.uID=IDR_MAINFRAME;

nf.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));

strcpy(nf.szTip,”星魔远程控制……..”);

strcpy(nf.szInfoTitle,”提示!”);

strcpy(nf.szInfo,”星魔远程控制已启动!”);

nf.uCallbackMessage=WM_SHOWTASK;

Shell_NotifyIcon(NIM_ADD,&nf);

初始化CListCtrl控件的CImageList.以及设置CListCtrl的风格

m_ImageList.Create(18, 18, ILC_COLOR32, 10, 0);

m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_COMPUTER));

CRect rect;

::GetWindowRect(m_ServerList.m_hWnd,&rect);

DWORD dwidth;

dwidth=rect.Width()/SERVERLISTCOLUMN;

m_ServerList.SetExtendedStyle(m_ServerList.GetExtendedStyle()|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);

m_ServerList.SetImageList(&m_ImageList,LVSIL_SMALL);


m_ServerList.InsertColumn(1,”所在地区”,LVCFMT_CENTER,dwidth);

m_ServerList.InsertColumn(2,”计算机名称”,LVCFMT_CENTER,dwidth);

m_ServerList.InsertColumn(3,”IP地址”,LVCFMT_CENTER,dwidth);

m_ServerList.InsertColumn(4,”内存”,LVCFMT_CENTER,dwidth);

m_ServerList.InsertColumn(5,”当前用户名”,LVCFMT_CENTER,dwidth);

m_ServerList.InsertColumn(6,”备注信息”,LVCFMT_CENTER,dwidth);

更改对话框的风格

DWORD style=WS_THICKFRAME|WS_MAXIMIZEBOX|WS_MINIMIZEBOX;

ModifyStyle(0,style);

让CListCtrl随窗口的大小的变化而改变,以使其适应窗口

MoveCtrl();

void CClient_Dlg::MoveCtrl()

{

if(m_ServerList.m_hWnd!=0)

{

   //首先移动CListCtrl,与窗口位置和大小保持一致

   //CRect Btrect;

   //((CButton*)GetDlgItem(IDOK))->GetClientRect(&Btrect);

  

   CRect rect;        //父窗口的位置

   GetClientRect(&rect);

//   m_ServerList.SetWindowPos(&wndTop,rect.left,rect.right,rect.Width(),rect.Height(),);

   rect.left=rect.left+5;

   rect.bottom=rect.bottom-5;

   rect.top=rect.top;

   rect.right=rect.right-5;

  

  

   m_ServerList.MoveWindow(&rect);

   CRect crect;

   ::GetWindowRect(m_ServerList.m_hWnd,&crect);

   DWORD dwidth;

   dwidth=crect.Width()/SERVERLISTCOLUMN;

   for(int i=0;i<=SERVERLISTCOLUMN;i++)

    m_ServerList.SetColumnWidth(i,dwidth);

}

}

开启心跳线程

HANDLE hd=CreateThread(NULL,0,KeepLive,this,0,NULL);

CloseHandle(hd);

心跳线程的代码部分

DWORD WINAPI CClient_Dlg::KeepLive(LPVOID lparm)

{

CClient_Dlg* ccd=(CClient_Dlg*)lparm;

CListCtrl* clc=&ccd->m_ServerList;

SOCKET sock;

int ServerNum=0;


while (1)

{

   ServerNum=clc->GetItemCount();

   for(int i=0;i<ServerNum;i++)

   {

    sock=(SOCKET)clc->GetItemData(i);

    if(SOCKET_ERROR==send(sock,”test”,sizeof(“test”),0))

    {

     clc->DeleteItem(i);

    }

  

   }

   Sleep(20000);

}

return 0;

}