《远控编程笔记》 第二天

第三课、

 一、客户端界面的设计和编写

 1.3 列表的列宽度支持伸缩 

  

1.CListCtrl  SetColumnWidth   查看MSDN

             BOOL SetColumnWidth(

                             int nCol,             //列索引

                             int cx                //列宽度

             );

2.在Dlg的CPP文件开始声明列总宽度变量:

            int g_Column_Online_Width=0;   //初始化上线列总宽度

            int g_Column_Message_Width=0;  //初始化日志列总宽度

3. 在initlist函数中计算列的总宽度(红色部分):

int CVeryEvilDlg::InitList(void)

{

//初始化上线列表控件

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

{

m_CList_Online.InsertColumn(i,g_Column_Data_Online[i].title,LVCFMT_CENTER,g_Column_Data_Online[i].nWidth);

g_Column_Online_Width+=g_Column_Data_Online[i].nWidth;       //得到总宽度

}

//初始化日志列表控件

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

{

m_CList_Message.InsertColumn(i,g_Column_Data_Message[i].title,LVCFMT_CENTER,g_Column_Data_Message[i].nWidth);

g_Column_Message_Width+=g_Column_Data_Message[i].nWidth;       //得到总宽度

}

return 0;

}

4.在OnSize函数中添加安百分比调整当前列的宽度代码(红色部分):

void CVeryEvilDlg::OnSize(UINT nType, int cx, int cy)

{//cx代表改变大小后的整个界面的宽度,cy代表改变大小后的整个界面的高度

CDialogEx::OnSize(nType, cx, cy);

double dcx=cx;     //保存对话框的总宽度

if (m_CList_Online.m_hWnd!=NULL)

{//判断控件变量是否和一个窗口句柄发生关联(如果关联则说明控件已经正确显示),避免出错

CRect rc;

rc.left=1;       //列表的左上角的X坐标

rc.top=80;       //列表的左上角的Y坐标

rc.right=cx-1;  //列表的右下角的X坐标

rc.bottom=cy-160;  //列表的右下角的Y坐标

m_CList_Online.MoveWindow(rc);//移动控件窗口到新位置

//按照以前的百分比重新计算每列的宽度并设置新的宽度

for(int i=0;i<g_Column_Count_Online;i++){         //遍历每一个列

double dd=g_Column_Data_Online[i].nWidth;     //得到当前列的宽度

dd/=g_Column_Online_Width;                    //看一看当前宽度占总长度的几分之几

dd*=dcx;                                      //用原来的长度乘以所占的几分之几得到当前的宽度

int lenth=(int)dd;                                 //转换为int 类型

m_CList_Online.SetColumnWidth(i,(lenth));     //设置当前的宽度

}

}

if (m_CList_Message.m_hWnd!=NULL)

{//判断控件变量是否和一个窗口句柄发生关联(如果关联则说明控件已经正确显示),避免出错

CRect rc;

rc.left=1;        //列表的左坐标

rc.top=cy-156;    //列表的上坐标

rc.right=cx-1;    //列表的右坐标

rc.bottom=cy-6;  //列表的下坐标

m_CList_Message.MoveWindow(rc);

//按照以前的百分比重新计算每列的宽度并设置新的宽度

for(int i=0;i<g_Column_Count_Message;i++){         //遍历每一个列

double dd=g_Column_Data_Message[i].nWidth;     //得到当前列的宽度

dd/=g_Column_Message_Width;                    //看一看当前宽度占总长度的几分之几

dd*=dcx;                                      //用原来的长度乘以所占的几分之几得到当前的宽度

int lenth=(int)dd;                                 //转换为int 类型

m_CList_Message.SetColumnWidth(i,(lenth));     //设置当前的宽度

}

}

}

5.注意这句

   double dcx=cx;     //保存对话框的总宽度

是为了保证精确度最少的丢失

注意:手动调整对话框界面的大小,使所有列的宽度和等于对话框的长度

 第四课客户端界面的设计和编写

1.4 列表中添加条目

用到的函数参数说明:

1.CListCtrl    InsertItem  插入条目

               int InsertItem(

                         int nItem,              //插入哪一行

                         LPCTSTR lpszItem        //该行0列显示的字符

               );

              SetItemText         设置哪个列的字符

              BOOL SetItemText(

                          int nItem,                   //改动那个行

                          int nSubItem,                //该行中那个子列

                          LPCTSTR lpszText             //要设置的字符

              );

2.列表设计思路:

             (1)服务端上线后要显示在列表中,这样有一个统一的函数来处理会使代码更加简洁。

             (2)消息显示分为成功失败两种,还要在其中显示消息产生的时间,这样也应该有一个统一的函数来处理。

                 

3.上线列表添加处理:

void CVeryEvilDlg::AddList(CString strIP, CString strAddr, CString strPCName, CString strOS, CString strCPU, CString strVideo, CString strPing)

{//当有主机上线是调用此函数

m_CList_Online.InsertItem(0,strIP);                               //默认为0行  这样所有插入的新列都在最上面

m_CList_Online.SetItemText(0,ONLINELIST_ADDR,strAddr);            //设置列的显示字符   这里 ONLINELIST_ADDR等 为第二节课中的枚举类型 用这样的方法

m_CList_Online.SetItemText(0,ONLINELIST_COMPUTER_NAME,strPCName); //解决问题会避免以后扩展时的冲突

m_CList_Online.SetItemText(0,ONLINELIST_OS,strOS); 

m_CList_Online.SetItemText(0,ONLINELIST_CPU,strCPU);

m_CList_Online.SetItemText(0,ONLINELIST_VIDEO,strVideo);

m_CList_Online.SetItemText(0,ONLINELIST_PING,strPing); 

}

4.添加日志消息的处理:

void CVeryEvilDlg::ShowMessage(bool bIsOK, CString strMsg)

{//当有消息需要在日志控件列表显示时是调用

CString strIsOK,strTime;

CTime t=CTime::GetCurrentTime();

strTime=t.Format("%H:%M:%S");

if (bIsOK)

{

strIsOK="执行成功";

}else{

strIsOK="执行失败";

}

 m_CList_Message.InsertItem(0,strIsOK);

 m_CList_Message.SetItemText(0,1,strTime);

 m_CList_Message.SetItemText(0,2,strMsg);

}

5.添加伪上线,和日志的测试代码,在没有加入gh0st传输内核之前是要自己测试的,所以要加入一个用于测试的函数:

void CVeryEvilDlg::Test(void)

{

AddList("192.168.0.1","本机局域网","Lang","Windows7","2.2GHZ","有","123232");

ShowMessage(true,"软件初始化成功...");

}

 然后在OnInitDialog  中添加调用:

                           Test();

6.设置两个列表空件点击时整个列都是选中状态样式

       在InitList()函数中加入代码:

       m_CList_Online.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES); //上线控件列表额外设置网格样式

       m_CList_Message.SetExtendedStyle(LVS_EX_FULLROWSELECT);

第五课客户端界面的设计和编写

1.5 列表中显示弹出菜单

  

1.添加菜单资源

2.功能菜单项并写入相应的菜单ID

3.显示菜单

   (1)参考gh0st代码,看一下gh0st是怎样显示菜单的

       a.找到主菜单

       b.查看主菜单的ID

       c.搜索IDR_LIST

       d.分析代码:

        CMenu popup;                  //声明一个菜单变量

popup.LoadMenu(IDR_LIST);       //载入菜单资源

CMenu* pM = popup.GetSubMenu(0);  //得到菜单项

CPoint p;

GetCursorPos(&p);                    //得到鼠标指针的位置

int count = pM->GetMenuItemCount();       //得到菜单的个数

if (m_pListCtrl->GetSelectedCount() == 0)  //如果没有选中列表中的条目

{

for (int i = 0; i < count - 2; i++)       //遍历每一个菜单

{

pM->EnableMenuItem(i, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);  //该项变灰

}

pM->EnableMenuItem(count - 1, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);

}

// 全选

if (m_pListCtrl->GetItemCount() > 0)    //列表中的条目项大于0     

pM->EnableMenuItem(count - 2, MF_BYPOSITION | MF_ENABLED);    //激活倒数第二个菜单 

else

pM->EnableMenuItem(count - 2, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);  //否则变灰

pM->TrackPopupMenu(TPM_LEFTALIGN, p.x, p.y, this);        //在指定位置显示菜单

}

   (2)添加我们的代码

为线上控件列表添加NM_CLICK消息响应函数,并添加如下处理代码

void CVeryEvilDlg::OnNMRClickOnline(NMHDR *pNMHDR, LRESULT *pResult)

{

LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

// TODO: 在此添加控件通知处理程序代码

CMenu popup;

popup.LoadMenu(IDR_MENU_ONLINE);

CMenu* pM = popup.GetSubMenu(0);//获取菜单项

CPoint p;

GetCursorPos(&p);//获取当前鼠标坐标

int count = pM->GetMenuItemCount();//获取菜单项目条数

if (m_CList_Online.GetSelectedCount() == 0)       //如果没有选中项目(空白区域)

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

{//遍历菜单项目逐个变灰

pM->EnableMenuItem(i, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);          

}

}

     pM->TrackPopupMenu(TPM_LEFTALIGN, p.x, p.y, this);

*pResult = 0;

}

你可能感兴趣的:(《远控编程笔记》 第二天)