C++类设计:一个不同版本的日志类(完整源码)

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。

 


        如何设计日志类请看:C++类设计:设计一个日志类(源码)_初级代码游戏的博客-CSDN博客        

        这个版本有些不同,支持输出到编辑框、文件和VS的输出窗口,基本结构完全相同。

目录

一、效果

二、完整源码

三、详解

3.1 输出到VS输出窗口

3.2 输出到编辑框

3.3 输出到文件


一、效果

        VS2017,MFC,UNICODE字符集。

        输出到编辑框:

        自动向下滚动,编辑框必须是多行的。

         输出到VS输出窗口(调试模式):

二、完整源码

        头文件:

//common.h#pragma once
#include <sstream>
#include <map>
using namespace std;extern CEdit* pGlobalLogWnd;class CStringConvert
{
public:static string WStringToString(wstring const& wstr){size_t buflen = wstr.size() * sizeof(wchar_t) + 1;char* buf = new char[buflen];WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, buf, (int)buflen, NULL, 0);string ret = buf;delete[] buf;return ret;}static wstring StringToWString(string const& str){//返回接受字符串所需缓冲区的大小,已经包含字符结尾符'\0'int iSize = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);wchar_t* buf = new wchar_t[iSize * sizeof(wchar_t)];MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, buf, iSize);wstring ret = buf;delete[] buf;return ret;}
};class CLog
{
private:HANDLE hFile = 0;//输出文件stringstream m_buf;//一条信息CString m_file;//产生日志的文件名int m_line;//产生日志的行号int m_limit_text = UINT_MAX;//最大长度,编辑框的默认值大概是几十K,需要设置得更大void end(char const* logtype){CString str;//格式化信息str += logtype;str += ":";str += m_buf.str().c_str();if (m_file.GetLength() > 0){CString line;line.Format(TEXT("%d"), m_line);str += TEXT(" [From ") + m_file + TEXT(":") + line + TEXT("]");}str += "\r\n";//输出到VS信息窗口OutputDebugString(str);//输出到文件if (hFile){DWORD dwCount;string mbcs_string = CStringConvert::WStringToString(str.GetString());WriteFile(hFile, mbcs_string.c_str(), (DWORD)mbcs_string.size(), &dwCount, 0);}//输出到编辑框if (pGlobalLogWnd && ::IsWindow(pGlobalLogWnd->m_hWnd)){pGlobalLogWnd->SetLimitText(m_limit_text);while (pGlobalLogWnd->GetWindowTextLength() >= m_limit_text){//pGlobalLogWnd->SetSel(0, mag_size.begin()->second + 2);//pGlobalLogWnd->ReplaceSel(TEXT(""));//mag_size.erase(mag_size.begin());pGlobalLogWnd->SetWindowText(TEXT(""));}int nLength = pGlobalLogWnd->GetWindowTextLength();pGlobalLogWnd->SetSel(nLength, nLength);pGlobalLogWnd->ReplaceSel(str);pGlobalLogWnd->LineScroll(pGlobalLogWnd->GetLineCount());}else{OutputDebugString(TEXT("日志窗口失效\r\n"));}//清除缓存的信息m_buf.str("");m_file = "";m_line = 0;}
public:CLog(){wchar_t pszPathName[2048];GetModuleFileName(NULL, pszPathName, 2048);StrCat(pszPathName, TEXT(".log"));hFile = CreateFile(pszPathName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);if (INVALID_HANDLE_VALUE == hFile){MessageBox(NULL,TEXT("创建或打开日志文件失败"),TEXT("出错"),0);}}~CLog(){if (hFile)CloseHandle(hFile);}void set_LimitText(int n) { m_limit_text = n; }struct CLog_ende{};struct CLog_endi{};struct CLog_endd{};CLog& SetPos(char const * file, int line){m_file = file;m_line = line;return *this;}template<typename T>CLog& operator<<(T const& data){m_buf << data;return *this;}CLog& operator<<(CLog_ende const& data){end("错误");return *this;}CLog& operator<<(CLog_endi const& data){end("信息");return *this;}CLog& operator<<(CLog_endd const& data){end("调试");return *this;}CLog& operator<<(CString const& data){return operator<<(data.GetString());}CLog& operator<<(wchar_t const* data){return operator<<(CStringConvert::WStringToString(wstring(data)));}CLog& operator<<(RECT const& data){return *this << "{" << data.left << "," << data.top << "," << data.right << "," << data.bottom << "}";}
};extern bool G_IS_DEBUG;
extern CLog gloablLog;
#define thelog (gloablLog.SetPos( __FILE__ , __LINE__))
#define debuglog if(G_IS_DEBUG)gloablLog.SetPos( __FILE__ , __LINE__)
extern CLog::CLog_ende ende;
extern CLog::CLog_endi endi;
extern CLog::CLog_endd endd;

        源文件:

#include "pch.h"
#include "common.h"CEdit* pGlobalLogWnd = nullptr;bool G_IS_DEBUG = false;
CLog gloablLog;
CLog::CLog_ende ende;
CLog::CLog_endi endi;
CLog::CLog_endd endd;

        使用:

	//设置编辑框最大长度gloablLog.set_LimitText(1024 * 1024);//设置编辑框指针,不设置则不输出到编辑框pGlobalLogWnd = &this->m_LogWnd;//打开调试开关,否则debuglog不输出G_IS_DEBUG = true;//输入出日志:thelog<<a<<b<<c<<endi;thelog<<a<<b<<c<<ende;thelog<<a<<b<<c<<endd;debuglog<<a<<b<<c<<endi;debuglog<<a<<b<<c<<ende;debuglog<<a<<b<<c<<endd;

三、详解

3.1 输出到VS输出窗口

        在调试模式下可以直接输出到VS的输出窗口,使用如下函数即可:

debugapi.h
Kernel32.lib/Kernel32.dllvoid OutputDebugStringA([in, optional] LPCSTR lpOutputString
);

        不过如果不是调试模式就没用了。

3.2 输出到编辑框

        图形界面程序完全可以自带日志窗口,这里用了一个编辑框CEdit。用作日志的编辑框需要做一些设置:

  • 多行
  • 滚动条
  • 最大字符数大一些
  • 自动滚动

        前两个在窗体设计器设置即可,后两个靠代码:

		//输出到编辑框if (pGlobalLogWnd && ::IsWindow(pGlobalLogWnd->m_hWnd)){pGlobalLogWnd->SetLimitText(m_limit_text);while (pGlobalLogWnd->GetWindowTextLength() >= m_limit_text){//pGlobalLogWnd->SetSel(0, mag_size.begin()->second + 2);//pGlobalLogWnd->ReplaceSel(TEXT(""));//mag_size.erase(mag_size.begin());pGlobalLogWnd->SetWindowText(TEXT(""));}int nLength = pGlobalLogWnd->GetWindowTextLength();pGlobalLogWnd->SetSel(nLength, nLength);pGlobalLogWnd->ReplaceSel(str);pGlobalLogWnd->LineScroll(pGlobalLogWnd->GetLineCount());}

        编辑框的修改要用ReplaceSel,不能用SetWindowText,会严重闪烁。

3.3 输出到文件

        输出到文件没什么好解释了,要注意的就是输出文件的编码,尽量用utf-8,兼容性比较好。如果输出宽字符,用记事本打开可能乱码(或许是没有添加BOM的原因,总之utf-8最简单啦)。


(这里是结束)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/585768.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小清新卡通人物静态404源码

源码介绍 小清新卡通人物静态404源码&#xff0c;可以做自己的网站错误页面&#xff0c;记事本修改上传服务器即可 源码下载 小清新卡通人物静态404源码

如何用Git在终端以可视化的方式查看提交情况

2024年4月2日&#xff0c;周二上午 要使用 Git 查看树状提交情况&#xff0c;可以使用 git log 命令的 --graph 选项。这个选项会以树状图的形式显示提交历史&#xff0c;清晰地展示每个提交的分支合并情况和分支间的关系。 git log --graph 除了 --graph 选项外&#xff0c;还…

ZooKeeper 的持久化机制

持久化的定义&#xff1a; 数据&#xff0c;存到磁盘或者文件当中。机器重启后&#xff0c;数据不会丢失。内存 -> 磁盘的映射&#xff0c;和序列化有些像。 ZooKeeper 的持久化&#xff1a; SnapShot 快照&#xff0c;记录内存中的全量数据TxnLog 增量事务日志&#xff…

Java接口与继承实践:Ether通信系统的构建(day16)

创建一个接口Icontroller, 再创建一个接口IReceiver, 创建一个子类实现IReceiver&#xff0c; 创建一个子类实现IContrller&#xff0c; 创建一个类Ether 创建一个Signal类 创建一个类Radiosignal继承Signal 创建一个用户User 最后创建一个Main类 今日总结&#xff1a…

交易所上币:区块链项目上线交易所流程

一、了解交易所/申请上币 在区块链项目上线交易所之前,首先需要对交易所进行充分的了解,包括交易所的基本信息、交易规则、飞BTC5186上币标准等。还需要了解交易所的申请上币流程,以便为后续的操作做好准备。 1.1 选择合适的交易所 在众多的交易所中 飞(BTC5186),如何选择一个…

基于springboot+vue+Mysql的火车订票管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

【面试八股总结】传输控制协议TCP(一)

一、什么是TCP协议 TCP是传输控制协议Transmission Control Protocol TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。 面向连接的&#xff1a;每条TCP连接杜只能有两个端点&#xff0c;每一条TCP连接只能是点对点的&#xff08;一对一&#xff09;可靠的&#xff1a…

Mysql实战--为什么表数据删掉一半,表文件大小不变

经常会有同学来问我&#xff0c;我的数据库占用空间太大&#xff0c;我把一个最大的表删掉了一半的数据&#xff0c;怎么表文件的大小还是没变&#xff1f; 那么今天&#xff0c;我就和你聊聊数据库表的空间回收&#xff0c;看看如何解决这个问题。 这里&#xff0c;我们还是针…

Day78:服务攻防-数据库安全RedisCouchDBH2database未授权访问CVE漏洞

目录 前置知识 数据库应用-Redis-未授权访问&CVE漏洞 未授权访问&#xff1a;CNVD-2015-07557 未授权访问-CNVD-2019-21763 未授权访问-沙箱绕过RCE-CVE-2022-0543 数据库应用-Couchdb-未授权越权&CVE漏洞 Couchdb 垂直权限绕过&#xff08;CVE-2017-12635&…

每天五分钟计算机视觉:如何基于滑动窗口技术完成目标的检测?

汽车检测算法 现在我们想要构建一个汽车检测算法,我们希望输入到算法中一张图片,算法就可以帮助我们检测出这张图片中是否有汽车。 数据集 首先创建一个标签训练集,x是样本,y是标签。我们的训练集最好是被剪切过的图片,剪掉汽车以外的部分,使汽车居于中间位置,就是整张…

Wheel Controller 3D

Wheel Controller 3D是Unity内置WheelCollider的完整替代品。它允许更真实的车辆行为、完全定制和3D地面检测。 Wheel Controller 3D是Unity内置WheelCollider的完整替代品。它允许更真实的车辆行为、完全定制和3D地面检测。 如果您正在寻找包含Wheel Controller 3D的完整车辆物…

第十四届蓝桥杯(八题C++ 题目+代码+注解)

目录 题目一&#xff08;日期统计 纯暴力&#xff09;&#xff1a; 代码&#xff1a; 题目二&#xff08;01串的熵 模拟&#xff09;&#xff1a; 代码&#xff1a; 题目三&#xff08;治炼金属&#xff09;&#xff1a; 代码&#xff1a; 题目四&#xff08;飞机降落 深度…