之前做小工具用VB比较多,但是实在无法忍受VB的扯淡语法,于是决定换成VC,毕竟C++跟C还是比较相像的。最近用MFC做了一个小工具,算是第一次用它。这里记下一些函数及其功能,供以后查询。
// 属性中设置Sort为None,View为Report CListCtrl DeviceList; //设置表格显示风格 绘制网格边框 整行选取 DeviceList.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT); //添加列 并设置列首(名称) 列宽 DeviceList.InsertColumn(0, _T("IP地址"), LVCFMT_LEFT, 110 ); DeviceList.InsertColumn(1, _T("MAC地址"), LVCFMT_LEFT, 130 ); //在count处添加一行 并设置此行首列文本为addrStr DeviceList.InsertItem(count,addrStr); //设置第i行第3列(行列都是从0计数)文本 DeviceList.SetItemText(i,3,_T("连接失败!")); //获取行数 int count=DeviceList.GetItemCount(); //判断i行是否被选中 if(DeviceList.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED) //删除所有行 DeviceList.DeleteAllItems(); //设置第i行为选中状态 DeviceList.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); //获取第i行第j列文本 CString strSelected=DeviceList.GetItemText(i,j);
//获取文本 CString cstr; TestText.GetWindowText(cstr); //设置文本 TestText.SetWindowText(cstr); //改写获取文本函数,更符合直觉,虽然说效率可能不高 CString GetWndText(CEdit *TarText) { CString cstr; TarText->GetWindowText(cstr); return cstr; } //在文本框尾部添加文本 void CEditAppendText(CEdit *TarText, CString *text) { int nLength = TarText->GetWindowTextLength(); if((nLength + text->GetLength()) > 30000) { TarText->SetSel(0, nLength / 2); TarText->ReplaceSel(_T("")); nLength = TarText->GetWindowTextLength(); } TarText->SetSel(nLength, nLength); TarText->ReplaceSel(*text); } void CEditAppendText(CEdit *TarText, wchar_t *text) { CString cstr = text; CEditAppendText(TarText, &cstr); } void CEditAppendText(CEdit *TarText, char *text) { wchar_t wcstring[2048]; MultiByteToWideChar(CP_ACP, 0, text, -1, wcstring, 2048); CString cstr = wcstring; CEditAppendText(TarText, &cstr); } //在CEdit中实现类似C中的Printf函数 #define PRINTF_BUFSIZE 10240 void CEditPrintf(CEdit *TarText, char *fmt, ...) { char buffer[PRINTF_BUFSIZE]; va_list arg_ptr; va_start(arg_ptr, fmt); vsnprintf_s(buffer, PRINTF_BUFSIZE, fmt, arg_ptr); CEditAppendText(TarText, buffer); va_end(arg_ptr); }
CComboBox AdapterList; //清空下拉列表项 AdapterList.ResetContent(); //获取当前选择项 int curSel=AdapterList.GetCurSel(); //获取列表总数 int cnt=AdapterList.GetCount(); //添加列表项 AdapterList.AddString(adapter);
//线程句柄 HANDLE devOpraHandle; //创建线程 HANDLE WINAPI CreateThread( //指向SECURITY_ATTRIBUTES型态的结构的指针。在Windows 98中忽略该参数。在Windows NT中,NULL使用默认安全性。 LPSECURITY_ATTRIBUTES lpThreadAttributes, /* 设置初始栈的大小,以字节为单位,如果为0, 那么默认将使用与调用该函数的线程相同的栈空间大小。 任何情况下,Windows根据需要动态延长堆栈的大小。 */ SIZE_T dwStackSize, /* 指向线程函数的指针,形式:@函数名,函数名称没有限制,但是必须以下列形式声明:DWORD WINAPI 函数名 (LPVOID lpParam) ,格式不正确将无法调用成功。 也可以直接调用void类型,但lpStartAddress要通过LPTHREAD_START_ROUTINE转换如:(LPTHREAD_START_ROUTINE)MyVoid */ LPTHREAD_START_ROUTINE lpStartAddress, //向线程函数传递的参数,是一个指向结构的指针,不需传递参数时,为NULL。 LPVOID lpParameter, /* 线程标志,可取值如下: CREATE_SUSPENDED(0x00000004):创建一个挂起的线程, 0 :表示创建后立即激活。 */ DWORD dwCreationFlags, //保存新线程的id。无需返回线程ID时设为NULL LPDWORD lpThreadId ); devOpraHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadDevOpra, this, CREATE_SUSPENDED, NULL); /* 一般并不推荐使用 CreateThread函数,因为C的标准库有很多的全局变量。 例如,出错号、文件句柄等。 当线程的函数用到了C的标准库的时候,很容易导致冲突。 推荐使用RTL库里的System单元中定义的 BeginThread函数, 因为这除了能创建一个线程和一个入口函数以外,还增加了几项保护措施。 在MFC程序中,应该调用AfxBeginThread函数, 在Visual C++程序中应调用_beginthreadex函数。 */ //挂起线程 SuspendThread(devOpraHandle); //恢复线程 ResumeThread(devOpraHandle);
//htons():16位数据按字节反转 //htonl():32位数据按字节反转 //将一个用网际标准点分表示法表示的字符串地址转换成网际地址值。 ULONG ip = inet_addr("192.168.0.100"); //将一个网际地址值转换成一个用点分十进制表示法表示的字符串地址 inet_ntoa(ip); //定义套接字 SOCKET sockBootp; //关闭套接字 closesocket(sockBootp); /* 新建套接字。 af: 地址格式描述,一般使用AF_INET type: SOCK_DGRAM 使用UDP协议,无连接 SOCK_STREAM 使用TCP协议,有连接 protocol: 协议类型 不指定 默认为0 返回值: 如果没有错误发生,socket()返回一个与建立的套接字相关的描述符。 否则它返回值INVALID_SOCKET,错误码可通过调用WSAGetLastError()函数得到。 */ SOCKET WSAAPI socket(int af, int type, int protocol); //示例 sockBootp = socket(AF_INET, SOCK_DGRAM, 0); /* 设置套接字选项 s: 套接字描述符。 level: 选项定义的层次,只支持SOL_SOCKET和IPPROTO_TCP。 optname: 指定套接字选项的名字。 optval: 指向请求选项数据缓冲区的指针。 optlen: 选项数据optval缓冲区的长度。 返回值: 如果没有错误发生,setsockopt()返回0。否则它返回值SOCKET_ERROR, 错误码可通过调用WSAGetLastError()函数得到。 */ setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen); //示例 //设置允许发送广播数据,只对UDP套接字有效 int broad = 1; setsockopt(sockBootp, SOL_SOCKET, SO_BROADCAST, (const char *)&broad, sizeof(broad)); //设置接收等待时间 接收超时 单位ms int recvTimeOut = BOOTP_SCKTO; setsockopt(sockBootp, SOL_SOCKET, SO_RCVTIMEO, (char *)&recvTimeOut, sizeof(int)); /* closesocket后套接字立即关闭, 并且缓存的数据将不再被发送。 如果bDontLinger = TRUE closesocket()调用将立即返回。 但是排队等待传送的任何数据如果可能的话 都将在该套接字关闭前发送出去 只对TCP套接字有效 */ BOOL bDontLinger = FALSE; setsockopt(sockBootp, SOL_SOCKET, SO_DONTLINGER, (const char *)&bDontLinger, sizeof(BOOL)); /* 绑定本地端口和地址。 s: 指示未连接的数据报或流套接字的描述符。 name: 赋给套接字的本地地址。 namelen:地址缓冲区长度。 返回值: 如果没有错误发生,bind()返回0。否则返回值SOCKET_ERROR, 错误码可通过调用WSAGetLastError()函数得到。 */ int WSAAPI bind(SOCKET s, const struct SOCKADDR *name, int namelen); //示例 SOCKADDR_IN addrLocal; /* 此处localAddr为本地主机的网络接口地址。 可指定某个特定网络接口的地址。例如 inet_addr("192.168.0.100"); 也可指定为INADDR_ANY,即程序可以使用任何一个本地网络接口。 */ addrLocal.sin_addr.S_un.S_addr = localAddr; //地址类型,指定AF_INET addrLocal.sin_family = AF_INET; //端口号,必须为网络字节序,例如htons(80),即80端口 addrLocal.sin_port = htons(BOOTP_SERVER_PORT); bind(sockBootp, (SOCKADDR *)&addrLocal, sizeof(SOCKADDR))
(未完待续)