跳转至

windows程序

python通过传入的变量生成setter getter方法

代码如下所示:

Python
import sys
import os
import subprocess
import platform

# 获取当前目录
current_directory = os.path.dirname(os.path.abspath(sys.argv[0]))


def camel_case_split(identifier):
    components = identifier.split("_")
    return "".join(x.title() for x in components)


def create_getter_setter(input_string, class_name):
    lines = input_string.strip().split("\n")
    data = []
    hppFunctionRows = []
    cppContents = []
    variable_names = []
    print("\n")

    type_config = {
        "int": {"prefix": "m_n", "initValue": "0"},
        "double": {"prefix": "m_d", "initValue": "0.0"},
        "CString": {"prefix": "m_str", "initValue": '_T("")'},
        "bool": {"prefix": "m_b", "initValue": "false"},
        "AcGePoint3d": {"prefix": "m_pt", "initValue": "AcGePoint3d::kOrigin"},
        "AcGeMatrix3d": {"prefix": "m_mat", "initValue": "AcGeMatrix3d::kIdentity"},
        "AcGeVector2d": {"prefix": "m_vec", "initValue": "AcGeVector2d::kXAxis"},
        "AcGeVector3d": {"prefix": "m_vec", "initValue": "AcGeVector3d::kXAxis"},
        "AcGePoint2d": {"prefix": "m_pt", "initValue": "AcGePoint2d::kOrigin"},
        # 默认配置cle
        "default": {"prefix": "m_", "initValue": "nullptr"},
    }
    try:
        for line in lines:
            line = line.strip()
            var_comment = "" if "//" not in line else line.split("//")[1].strip()
            var_declaration = line.split("//")[0].strip()

            var_type, var_name = var_declaration.split()[:2]
            var_name = var_name.replace(";", "")

            # 使用配置化处理
            prefix, initValue = type_config.get(
                var_type, type_config["default"]
            ).values()

            method_suffix = camel_case_split(
                var_name.split(prefix)[1] if prefix in var_name else var_name
            )

            init = f"{var_name}({initValue}),//{var_comment}"
            variable_names.append(init)

            getter_method = (
                f"//获取{var_comment}\n"
                f"{var_type} {class_name}::get{method_suffix}() const\n"
                "{\n"
                f"    return {var_name};\n"
                "}\n"
            )
            cppContents.append(getter_method)

            setter_method = (
                f"//设置{var_comment}\n"
                f"void {class_name}::set{method_suffix}({var_type} value)\n"
                "{\n"
                f"    {var_name} = value;\n"
                "}\n"
            )
            cppContents.append(setter_method)

            function_name = (
                f"//获取{var_comment}\n"
                f"{var_type} get{method_suffix}() const;\n"
                f"//设置{var_comment}\n"
                f"void set{method_suffix}({var_type} value);\n"
            )
            hppFunctionRows.append(function_name)

            row = f"{var_name} = other.get{method_suffix}();//获取{var_comment}\n"
            data.append(row)

    except Exception as e:
        print(e)
        return

    # 构造函数
    operate_method = (
        f"//构造函数\n"
        f"{class_name}& {class_name}::operator=(const {class_name}& other)\n"
        "{\n"
        f"  if (this != &other)\n"
        "   {\n"
        f"{''.join(data)}\n"
        "   }\n"
        f"  return *this;\n"
        "}\n"
    )
    cppContents.append(operate_method)

    # 异常处理增强
    try:
        # 检查列表是否不为空并且最后一个元素包含逗号
        variable_names = dealwithListInfo(variable_names)

        with open(f"{current_directory}/{class_name}.md", "w", encoding="utf-8") as f:
            f.write("* 初始化列表信息\n")
            f.write("```cpp\n")
            for i in variable_names:
                f.write(i + "\n")
            f.write("```\n")
            f.write("* 头文件信息\n")
            f.write("```cpp\n")
            f.write("".join(hppFunctionRows))
            # for i in hppFunctionRows:
            #     f.write(i+ "\n")
            f.write(f"{class_name}& operator=(const {class_name}& other);\n")
            f.write("private:\n")
            for line in lines:
                f.write(line + "\n")
            f.write("```\n")
            f.write("* cpp函数信息\n")
            f.write("```cpp\n")
            f.write("".join(cppContents))
            f.write("```\n")

    except IOError as e:
        print(f"文件操作失败: {e}")

    print("生成初始化列表\n")
    for i in variable_names:
        print(i)
    # 打开文件

    # 根据操作系统打开目录
    fileName = current_directory + "\\" + class_name + ".md"
    # 处理windows中的反斜杠
    if platform.system() == "Windows":
        subprocess.run(["explorer", fileName])
    elif platform.system() == "Darwin":  # macOS
        subprocess.run(["open", fileName])
    else:  # Assuming Linux or other Unix-like systems
        subprocess.run(["xdg-open", fileName])


# 示例输入
input_string1 = """int m_nShaft_diameter_row;            //轴径行
int m_nShaft_diameter_col;            //轴径列
double m_dShaft_diameter;                  //轴径 d1
double m_dCavity_diameter;                 //腔体直径 D
double m_dHole_depth;                      //高度 b
CString m_strInfo;//信息相关
"""


def dealwithListInfo(my_list):
    # 检查列表是否不为空并且最后一个元素包含逗号
    if my_list and "," in my_list[-1]:
        # 将最后一个元素转化为字符串(保证它是字符串格式)
        last_element = str(my_list[-1])
        # 查找最后一个逗号的位置
        last_comma_index = last_element.rfind(",")
        # 当找到最后一个逗号时
        if last_comma_index != -1:
            # 仅删除这个逗号:创造一个没有最后一个逗号的新字符串
            my_list[-1] = (
                last_element[:last_comma_index] + last_element[last_comma_index + 1 :]
            )
        return my_list


if __name__ == "__main__":
    print(
        "请输入变量定义的字符串,每行一个变量定义,结束后请按Ctrl+Z(Windows)或Ctrl+D(Linux/macOS)并回车:"
    )
    input_string = ""
    try:
        while True:
            line = input()
            input_string += line + "\n"
    except EOFError:  # 当用户结束输入时(Ctrl+D/Linux/macOS, Ctrl+Z/Windows)
        pass

    class_name = input("请输入类名:")
    if class_name == "":
        class_name = "CTableParameterInfo"
    create_getter_setter(input_string, class_name)

结果如下所示:

C++
生成初始化列表

m_nShaft_diameter_row(0),//轴径行   
m_nShaft_diameter_col(0),//轴径列   
m_dShaft_diameter(0.0),//轴径 d1    
m_dCavity_diameter(0.0),//腔体直径 D
m_dHole_depth(0.0),//高度 b
m_strInfo(_T("")),//信息相关    

//CTableParameterInfo.h
//获取轴径行
int CTableParameterInfo::getShaftDiameterRow() const;
//设置轴径行
void setShaftDiameterRow(int value);
//获取轴径列
int CTableParameterInfo::getShaftDiameterCol() const;
//设置轴径列
void setShaftDiameterCol(int value);
//获取轴径 d1
double CTableParameterInfo::getShaftDiameter() const;
//设置轴径 d1
void setShaftDiameter(double value);
//获取腔体直径 D
double CTableParameterInfo::getCavityDiameter() const;
//设置腔体直径 D
void setCavityDiameter(double value);
//获取高度 b
double CTableParameterInfo::getHoleDepth() const;
//设置高度 b
void setHoleDepth(double value);
//获取信息相关
CString CTableParameterInfo::getInfo() const;
//设置信息相关
void setInfo(CString value);
CTableParameterInfo& operator=(const CTableParameterInfo& other);
private:
int m_nShaft_diameter_row;            //轴径行
    int m_nShaft_diameter_col;            //轴径列
    double m_dShaft_diameter;                  //轴径 d1
    double m_dCavity_diameter;                 //腔体直径 D
    double m_dHole_depth;                      //高度 b
    CString m_strInfo;//信息相关

//CTableParameterInfo.cpp
//获取轴径行
int CTableParameterInfo::getShaftDiameterRow() const
{
    return m_nShaft_diameter_row;
}
//设置轴径行
void CTableParameterInfo::setShaftDiameterRow(int value)
{
    m_nShaft_diameter_row = value;
}
//获取轴径列
int CTableParameterInfo::getShaftDiameterCol() const
{
    return m_nShaft_diameter_col;
}
//设置轴径列
void CTableParameterInfo::setShaftDiameterCol(int value)
{
    m_nShaft_diameter_col = value;
}
//获取轴径 d1
double CTableParameterInfo::getShaftDiameter() const
{
    return m_dShaft_diameter;
}
//设置轴径 d1
void CTableParameterInfo::setShaftDiameter(double value)
{
    m_dShaft_diameter = value;
}
//获取腔体直径 D
double CTableParameterInfo::getCavityDiameter() const
{
    return m_dCavity_diameter;
}
//设置腔体直径 D
void CTableParameterInfo::setCavityDiameter(double value)
{
    m_dCavity_diameter = value;
}
//获取高度 b
double CTableParameterInfo::getHoleDepth() const
{
    return m_dHole_depth;
}
//设置高度 b
void CTableParameterInfo::setHoleDepth(double value)
{
    m_dHole_depth = value;
}
//获取信息相关
CString CTableParameterInfo::getInfo() const
{
    return m_strInfo;
}
//设置信息相关
void CTableParameterInfo::setInfo(CString value)
{
    m_strInfo = value;
}
//构造函数
CTableParameterInfo& CTableParameterInfo::operator=(const CTableParameterInfo& other)
{
  if (this != &other)
   {
m_nShaft_diameter_row = other.getShaftDiameterRow();//获取轴径行
m_nShaft_diameter_col = other.getShaftDiameterCol();//获取轴径列
m_dShaft_diameter = other.getShaftDiameter();//获取轴径 d1
m_dCavity_diameter = other.getCavityDiameter();//获取腔体直径 D
m_dHole_depth = other.getHoleDepth();//获取高度 b
m_strInfo = other.getInfo();//获取信息相关

   }
  return *this;
}

自定义实体Trim和Extend

Derive from AcDbCurve and implement AcDbCurve virtual members.

Extend

C++
1
2
3
4
5
    virtual Acad::ErrorStatus subGetStretchPoints(
        AcGePoint3dArray& stretchPoints) const;
    virtual Acad::ErrorStatus subMoveStretchPointsAt(
        const AcDbIntArray & indices,
        const AcGeVector3d& offset

实现以上两个函数

Trim

C++
virtual Acad::ErrorStatus subIntersectWith(const AcDbEntity * ent,
        AcDb::Intersect intType,
        AcGePoint3dArray & points,
        Adesk::GsMarker thisGsMarker,
        Adesk::GsMarker otherGsMarker) const;
    virtual Acad::ErrorStatus subIntersectWith(
        const AcDbEntity* pEnt,
        AcDb::Intersect intType,
        const AcGePlane& projPlane,
        AcGePoint3dArray& points,
        Adesk::GsMarker thisGsMarker = 0,
        Adesk::GsMarker otherGsMarker = 0
    ) const;

实现以上两个函数

ARX动态块相关操作

image-20240322164856228

第一个直接传入块参照的id即可创建AcDbDynBlockReference对象,便可对该块参照进行数据获取和修改。 第二个传入的是块参照的指针,如果该指针是以读打开的,该AcDbDynBlockReference对象只能进行数据读取,不能修改该块参照。


得到动态块参照的自定义属性

C++
std::map<CString, CString>  GetCustomParam(const AcDbObjectId& idBlkRef)
{
    std::map<CString, CString> mapName;

    AcDbDynBlockReferencePropertyArray DynBlkRefPropArray;  //动态块参照属性数组
    AcDbDynBlockReference DynBlkRef(idBlkRef);          //动态块参照对象
    DynBlkRef.getBlockProperties(DynBlkRefPropArray);
    AcDbDynBlockReferenceProperty DynBlockReferenceProp;    //动态块参照属性

    for (int i = 0; i < DynBlkRefPropArray.length(); i++)
    {
        DynBlockReferenceProp = DynBlkRefPropArray.at(i);

        bool bShow = DynBlockReferenceProp.show();          //是否在面板中显示
        auto type = DynBlockReferenceProp.propertyType();   //属性类型
        CString strName = DynBlockReferenceProp.propertyName().kwszPtr();   //属性名
        if (true == bShow)
        {

            CString strValue;
            AcDbEvalVariant value = DynBlockReferenceProp.value();//值
            if (DwgDataType::kDwgText == type)
            {
                strValue = value.resval.rstring;
            }
            else if (DwgDataType::kDwgReal == type)
            {
                strValue.Format(_T("%.2f"), value.resval.rreal);
            }
            mapName[strName] = strValue;
        }
    }
    return mapName;
}

其中,AcDbDynBlockReferenceProperty::value函数只能得到该属性当前设置的值。 对于多种数据这种情况,可以使用AcDbDynBlockReferenceProperty::getAllowedValues函数。


设置块参照的自定义属性

C++
bool SetCustomParam(const AcDbObjectId& idBlkRef,const std::map<CString, CString>& mapParam)
{
    AcDbDynBlockReferencePropertyArray DynBlkRefPropArray;  //动态块参照属性数组
    AcDbDynBlockReference DynBlkRef(idBlkRef);          //动态块参照对象
    DynBlkRef.getBlockProperties(DynBlkRefPropArray);
    AcDbDynBlockReferenceProperty DynBlockReferenceProp;    //动态块参照属性

    std::map<CString, CString>::const_iterator iter;
    for (iter = mapParam.begin(); iter != mapParam.end(); ++iter)
    {
        CString strKey = iter->first;
        CString strValue = iter->second;
        for (int i = 0; i < DynBlkRefPropArray.length(); i++)
        {
            DynBlockReferenceProp = DynBlkRefPropArray.at(i);

            bool bShow = DynBlockReferenceProp.show();          //是否在面板中显示
            if (false == bShow && DynBlockReferenceProp.readOnly() == true)
                continue;
            CString strName = DynBlockReferenceProp.propertyName().kwszPtr();   //属性名
            if (strName != strKey)
                continue;
            auto type = DynBlockReferenceProp.propertyType();   //属性类型
            if (DwgDataType::kDwgText == type)
            {
                AcDbEvalVariant value(strValue);
                DynBlockReferenceProp.setValue(value);
            }
            else if (DwgDataType::kDwgReal == type)
            {
                AcDbEvalVariant value(_wtof(strValue));
                DynBlockReferenceProp.setValue(value);
            }
        }
    }

    return true;
}

获取ACAD背景色的两种方案:

  • 在这种情况下,我们可以使用函数**unsigned long acedGetRGB(int color);** 使用参数 0 来获取背景颜色。
  • 另一种选择是使用 acedGetCurrentColors 函数,您可以从中获取 dwGfxModelBkColor 和 dwGfxLayoutBkColor 并(取决于tilemode值)使用您需要的。

acedGetRGB

C++
void CWHASSET::drawWipeOut(AcDbExtents exts, AcGiWorldDraw *mode)
{
    if (showFramFlag())
    {
        AcGePoint3d minPt, maxPt;
        minPt = exts.minPoint();
        maxPt = exts.maxPoint();
        AcGePoint3dArray wipePnts;
        wipePnts.append(minPt);
        wipePnts.append(AcGePoint3d(minPt.x, maxPt.y, minPt.z));
        wipePnts.append(maxPt);
        wipePnts.append(AcGePoint3d(maxPt.x, minPt.y, maxPt.z));
        wipePnts.append(minPt);
        Adesk::UInt32 lColor = acedGetRGB(0);
        //UInt32需要转化成rgb数据
        int R = 0xFF & lColor;
        int G = 0xFF00 & lColor;
        G >>= 8;
        int B = 0xFF0000 & lColor;
        B >>= 16;AcCmEntityColor cmColor;
        cmColor.setRGB(R, G, B);
        mode->subEntityTraits().setTrueColor(cmColor);
        mode->subEntityTraits().setFillType(kAcGiFillAlways);
        mode->geometry().polygon(wipePnts.length(), wipePnts.asArrayPtr());
    }
}

acedGetCurrentColors

C++
void CWHASSET::drawWipeOut(AcDbExtents exts, AcGiWorldDraw *mode)
{
    if (showFramFlag())
    {
        AcGePoint3d minPt, maxPt;
        minPt = exts.minPoint();
        maxPt = exts.maxPoint();
        AcGePoint3dArray wipePnts;
        wipePnts.append(minPt);
        wipePnts.append(AcGePoint3d(minPt.x, maxPt.y, minPt.z));
        wipePnts.append(maxPt);
        wipePnts.append(AcGePoint3d(maxPt.x, minPt.y, maxPt.z));
        wipePnts.append(minPt);
        AcColorSettings colorSetings; 
        acedGetCurrentColors(&colorSetings);
        AcCmEntityColor bgColor;
        if (!mode->context()->isPlotGeneration())
        {
            COLORREF rgbColor = (COLORREF)colorSetings.dwGfxModelBkColor;
            int red = rgbColor & 255;
            int green = rgbColor >> 8 & 255;
            int blue = rgbColor >> 16 & 255;
            bgColor.setRed(red);
            bgColor.setBlue(blue);
            bgColor.setGreen(green);
            mode->subEntityTraits().setTrueColor(bgColor);
        }
        else
        {
            COLORREF rgbColor = (COLORREF)colorSetings.dwGfxLayoutBkColor;
            int red = rgbColor & 255;
            int green = rgbColor >> 8 & 255;
            int blue = rgbColor >> 16 & 255;
            bgColor.setRed(red);
            bgColor.setBlue(blue);
            bgColor.setGreen(green);
            mode->subEntityTraits().setTrueColor(bgColor);
        }

        mode->subEntityTraits().setFillType(kAcGiFillAlways);
        mode->geometry().polygon(wipePnts.length(), wipePnts.asArrayPtr());
    }
}

ARX将区域内实体转成BMP

C++
static void MyGroupTEST()
{
    //框选区域
    AcGePoint3d pt1, pt2;
    if (RTNORM != acedGetPoint(NULL, _T("\n第一角点"), asDblArray(pt1)))
        return;
    if (RTNORM != acedGetCorner(asDblArray(pt1), _T("\n第二角点"), asDblArray(pt2)))
        return;
    //用户坐标系转世界坐标系
    pt1 = TransformPoint(pt1, 1, 0);
    pt2 = TransformPoint(pt2, 1, 0);

    //pt1 = PublicFunction::TransUcs2Wcs(pt1);
    //pt2 = PublicFunction::TransUcs2Wcs(pt2);
    ads_name sset;
    if (RTNORM != acedSSGet(_T("W"), p1, p2, NULL, sset))
    {
        return;
    }
    Adesk::Int32 sslen;
    acedSSLength(sset, &sslen);
    ads_name ename;
    AcDbObjectId entId = AcDbObjectId::kNull;
    AcDbObjectIdArray idArray;
    idArray.removeAll();
    for (int i=0; i<sslen; i++)
    {
        acedSSName(sset, i, ename);
        acdbGetObjectId(entId, ename);
        idArray.append(entId);
    }

    ads_ssfree(sset);
    if (idArray.isEmpty())
        return;
    //bmp
    POINT cp1 = GetPointInAcadCoordinate(pt1);
    POINT cp2 = GetPointInAcadCoordinate(pt2);
    if (cp1.x > cp2.x)
        std::swap(cp1, cp2);
    WriteToBmp(cp1, cp2);
    //wblock
    AcDbDatabase* pShortCutDwg = NULL;
    acdbCurDwg()->wblock(pShortCutDwg, idArray, AcGePoint3d(0.0, 0.0, 0.0));
    pShortCutDwg->saveAs(_T("D:\\a.dwg"));
    delete pShortCutDwg;
    pShortCutDwg = NULL;

}

工具代码:

C++
AcGePoint3d TransformPoint(const AcGePoint3d &point, int nFromType, int nToType)
{
    AcGePoint3d pt;
    //从ucs转到wcs
    struct resbuf rbFrom, rbTo;
    rbFrom.restype = RTSHORT;
    rbFrom.resval.rint = nFromType; // from wcs
    rbTo.restype = RTSHORT;
    rbTo.resval.rint = nToType;     // from ucs
    acedTrans(asDblArray(point), &rbFrom, &rbTo, Adesk::kFalse, asDblArray(pt));
    return pt;
}

POINT GetPointInAcadCoordinate(const AcGePoint3d &pt)
{
    ads_point pnt;
    ads_point_set(asDblArray(pt), pnt);
    //获取视口编号
    int wndNum = 0;
    struct resbuf v;
    if (acedGetVar(_T("cvport"), &v) == RTNORM)
    {
        wndNum = v.resval.rint;
    }
    //将pt坐标转为pixel屏幕坐标
    CPoint ptInScreen;
    acedCoordFromWorldToPixel(wndNum, pnt, ptInScreen);
    //将ptInScreen转为在view上的点p3
    POINT p3;
    p3.x = ptInScreen.x; p3.y = ptInScreen.y;
    ::ClientToScreen(acedGetAcadDwgView()->m_hWnd, &p3);
    return p3;
}

void WriteToBmp(const POINT& pt1, const POINT& pt2)
{
    //获得屏幕的HWND
    HWND hWnd = ::GetDesktopWindow();
    //获得屏幕的HDC
    HDC hScreenDC = ::GetDC(hWnd);
    HDC MemDC = ::CreateCompatibleDC(hScreenDC);
    RECT rect;
    ::GetWindowRect(hWnd, &rect);
    SIZE screensize;
    screensize.cx = abs(pt1.x - pt2.x);
    screensize.cy = abs(pt1.y - pt2.y);
    HBITMAP hBitmap = ::CreateCompatibleBitmap(hScreenDC, screensize.cx, screensize.cy);
    HGDIOBJ hOldBMP = ::SelectObject(MemDC, hBitmap);
    ::BitBlt(MemDC, 0, 0, screensize.cx, screensize.cy, hScreenDC, pt1.x, pt1.y, SRCCOPY);
    ::SelectObject(MemDC, hOldBMP);
    ::DeleteObject(MemDC);
    ::ReleaseDC(hWnd, hScreenDC);

    HDC hDC = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
    //当前分辨率下每个像素所占字节数
    int iBits = ::GetDeviceCaps(hDC, BITSPIXEL) * ::GetDeviceCaps(hDC, PLANES);
    ::DeleteDC(hDC);
    //位图中每个像素所占字节数
    WORD wBitCount;
    if (iBits <= 1)
        wBitCount = 1;
    else if (iBits <= 4)
        wBitCount = 4;
    else if (iBits <= 8)
        wBitCount = 8;
    else if (iBits <= 24)
        wBitCount = 24;
    else
        wBitCount = iBits;
    //调色板大小, 位图中像素字节大小 
    DWORD dwPaletteSize = 0;
    if (wBitCount <= 8)
        dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD);

    //位图属性结构
    BITMAP bm;
    ::GetObject(hBitmap, sizeof(bm), (LPSTR)&bm);

    //位图信息头结构
    BITMAPINFOHEADER bi;
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bm.bmWidth;
    bi.biHeight = bm.bmHeight;
    bi.biPlanes = 1;
    bi.biBitCount = wBitCount;
    //BI_RGB表示位图没有压缩
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    DWORD dwBmBitsSize = ((bm.bmWidth * wBitCount + 31) / 32) * 4 * bm.bmHeight;
    //为位图内容分配内存
    HANDLE hDib = ::GlobalAlloc(GHND, dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
    LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
    *lpbi = bi;
    // 处理调色板 
    HANDLE hPal = ::GetStockObject(DEFAULT_PALETTE);
    HANDLE  hOldPal = NULL;
    if (hPal)
    {
        hDC = ::GetDC(NULL);
        hOldPal = SelectPalette(hDC, (HPALETTE)hPal, FALSE);
        RealizePalette(hDC);
    }
    // 获取该调色板下新的像素值
    ::GetDIBits(hDC, hBitmap, 0, (UINT)bm.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + dwPaletteSize, (BITMAPINFO*)lpbi, DIB_RGB_COLORS);
    //恢复调色板
    if (hOldPal)
    {
        SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
        RealizePalette(hDC);
        ::ReleaseDC(NULL, hDC);
    }
    //位图文件头结构
    BITMAPFILEHEADER bmfHdr;
    // "BM"
    bmfHdr.bfType = 0x4D42;
    // 设置位图文件头
    DWORD dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;
    bmfHdr.bfSize = dwDIBSize;
    bmfHdr.bfReserved1 = 0;
    bmfHdr.bfReserved2 = 0;
    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;
    //创建位图文件
    HANDLE hFile = CreateFile(_T("D:\\a.bmp"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    DWORD dwWritten;
    // 写入位图文件头
    WriteFile(hFile, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
    // 写入位图文件其余内容
    WriteFile(hFile, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
    //清除
    GlobalUnlock(hDib);
    GlobalFree(hDib);
    CloseHandle(hFile);
}

雪花算法计算唯一的UUID

利用现成的算法https://github.com/sniper00/snowflake-cpp github开源算法

A CPP port of Twitter's Snowflake id generation algorithm

Use

C++
1
2
3
4
5
6
7
8
9
    using snowflake_t = snowflake<1534832906275L>;
    snowflake_t uuid;
    uuid.init(1, 1);

    for (int64_t i = 0; i < 10000; ++i)
    {
        auto id = uuid.nextid();
        std::cout << id << "\n";
    }

CPP

Use with lock

C++
1
2
3
4
5
6
7
8
9
    using snowflake_t = snowflake<1534832906275L,std::mutex>;
    snowflake_t uuid;
    uuid.init(1, 1);

    for (int64_t i = 0; i < 10000; ++i)
    {
        auto id = uuid.nextid();
        std::cout << id << "\n";
    }

CPP

snowflake-cpp

C++
#pragma once
#include <cstdint>
#include <chrono>
#include <stdexcept>
#include <mutex>

class snowflake_nonlock
{
public:
    void lock()
    {
    }
    void unlock()
    {
    }
};

template<int64_t Twepoch, typename Lock = snowflake_nonlock>
class snowflake
{
    using lock_type = Lock;
    static constexpr int64_t TWEPOCH = Twepoch;
    static constexpr int64_t WORKER_ID_BITS = 5L;
    static constexpr int64_t DATACENTER_ID_BITS = 5L;
    static constexpr int64_t MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1;
    static constexpr int64_t MAX_DATACENTER_ID = (1 << DATACENTER_ID_BITS) - 1;
    static constexpr int64_t SEQUENCE_BITS = 12L;
    static constexpr int64_t WORKER_ID_SHIFT = SEQUENCE_BITS;
    static constexpr int64_t DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
    static constexpr int64_t TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
    static constexpr int64_t SEQUENCE_MASK = (1 << SEQUENCE_BITS) - 1;

    using time_point = std::chrono::time_point<std::chrono::steady_clock>;

    time_point start_time_point_ = std::chrono::steady_clock::now();
    int64_t start_millsecond_ = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();

    int64_t last_timestamp_ = -1;
    int64_t workerid_ = 0;
    int64_t datacenterid_ = 0;
    int64_t sequence_ = 0;
    lock_type lock_;
public:
    snowflake() = default;

    snowflake(const snowflake&) = delete;

    snowflake& operator=(const snowflake&) = delete;

    void init(int64_t workerid, int64_t datacenterid)
    {
        if (workerid > MAX_WORKER_ID || workerid < 0) {
            throw std::runtime_error("worker Id can't be greater than 31 or less than 0");
        }

        if (datacenterid > MAX_DATACENTER_ID || datacenterid < 0) {
            throw std::runtime_error("datacenter Id can't be greater than 31 or less than 0");
        }

        workerid_ = workerid;
        datacenterid_ = datacenterid;
    }

    int64_t nextid()
    {
        std::lock_guard<lock_type> lock(lock_);
        //std::chrono::steady_clock  cannot decrease as physical time moves forward
        auto timestamp = millsecond();
        if (last_timestamp_ == timestamp)
        {
            sequence_ = (sequence_ + 1)&SEQUENCE_MASK;
            if (sequence_ == 0)
            {
                timestamp = wait_next_millis(last_timestamp_);
            }
        }
        else
        {
            sequence_ = 0;
        }

        last_timestamp_ = timestamp;

        return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT)
            | (datacenterid_ << DATACENTER_ID_SHIFT)
            | (workerid_ << WORKER_ID_SHIFT)
            | sequence_;
    }

private:
    int64_t millsecond() const noexcept
    {
        auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time_point_);
        return start_millsecond_ + diff.count();
    }

    int64_t wait_next_millis(int64_t last) const noexcept
    {
        auto timestamp = millsecond();
        while (timestamp <= last)
        {
            timestamp = millsecond();
        }
        return timestamp;
    }
};

ftp上传下载文件

libcurl从ftp上获取文件列表信息,包含中文

C++
inline std::wstring to_wstring(std::string const& str)
{
    std::wstring ustr;
    int const length = MultiByteToWideChar(
        CP_UTF8, 0,
        str.c_str(), static_cast<int>(str.length()),
        nullptr, 0);
    if (length <= 0)
        return ustr;
    ustr.resize(static_cast<size_t>(length));
    int const result = MultiByteToWideChar(
        CP_UTF8, 0,
        str.c_str(), static_cast<int>(str.length()),
        const_cast<wchar_t*>(ustr.data()), length);
    if (result != length)
        ustr.clear();
    return ustr;
}

std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8Converter;

size_t WriteCallback(char* contents, size_t size, size_t nmemb, std::string* userp)
{
    size_t totalSize = size * nmemb;
    userp->append(contents, totalSize);
    return totalSize;
}
bool GetFtpFileList(const char* ftpUrl, const char* username, const char* password, CString& strResult)
{
    CURL* curl;
    CURLcode res;

    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if (curl)
    {
        std::string response;

        struct curl_slist* headers = NULL;
        headers = curl_slist_append(headers, "Accept: */*");
        string strUserName = username;
        string strPassWord = password;
        curl_easy_setopt(curl, CURLOPT_URL, ftpUrl);
        curl_easy_setopt(curl, CURLOPT_USERPWD, (strUserName + ":" + strPassWord).c_str());  // 密码和用户名以":"连接,如:"username:password"
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
        curl_easy_setopt(curl, CURLOPT_FTP_USE_EPRT, 1L);  // 使用更安全的EPR命令(如果支持)
        curl_easy_setopt(curl, CURLOPT_FTPLISTONLY, 1L);   // 只列出文件,不下载

        res = curl_easy_perform(curl);

        if (res != CURLE_OK)
        {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        }
        else
        {
            // 尝试将字符串转换为宽字符串以便正确显示中文等非ASCII字符
            std::wstring wideResponse = utf8Converter.from_bytes(response);
            std::wcout << L"FTP directory listing:\n";
            std::wcout << wideResponse.c_str() << std::endl;
            strResult = wideResponse.c_str();
        }

        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();

    return (res == CURLE_OK);
}
int GetFtpDirectoryList(const char* ftpUrl, const char* username, const char* password, const char* strRemotePath, vector<CString>& fileList)
{
    CURL* curl;
    CURLcode res;
    CString strRemote = strRemotePath;
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if (curl)
    {
        std::string response;

        curl_slist* headers = NULL;
        headers = curl_slist_append(headers, "Accept: */*");
        string strUserName = username;
        string strPassWord = password;
        curl_easy_setopt(curl, CURLOPT_URL, ftpUrl);
        curl_easy_setopt(curl, CURLOPT_USERPWD, (strUserName + ":" + strPassWord).c_str());  // 密码和用户名以":"连接,如:"username:password"
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
        curl_easy_setopt(curl, CURLOPT_FTP_USE_EPRT, 1L);  // 使用更安全的EPR命令(如果支持)
        curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L);   // 只列出目录内容

        res = curl_easy_perform(curl);

        if (res == CURLE_OK)
        {
            // 解析响应字符串,提取文件和子目录名
            // 这里假设FTP服务器返回的是NLST格式,每行一个条目
            std::wstring wideResponse = utf8Converter.from_bytes(response);
            CString strResult = wideResponse.c_str();
            vector<CString> dirVec;
            dirVec.clear();
            int nFind = strResult.Replace(_T("\r\n"), _T("\r\n"));
            if (nFind > 0)
            {
                // 使用CString::Find()函数找到第一个\r\n的位置
                int pos = strResult.Find(_T("\r\n"));
                // 循环遍历所有\r\n分隔符,并将字符串拆分成一个一个的
                while (pos != -1)
                {
                    // 获取当前分隔符之前的子串
                    CString subStr = strResult.Left(pos);
                    if ((subStr.CompareNoCase(_T(".")) == 0)
                        ||(subStr.CompareNoCase(_T("..")) == 0))
                    {
                        continue;
                    }

                    if (subStr.GetAt(subStr.GetLength() - 1) == _T('/'))
                    {
                        dirVec.push_back(strRemote + subStr);
                    }
                    strRemote.Replace(_T("/"), _T("\\"));

                    fileList.push_back(strRemote + subStr);
                    // 将字符串指针移动到下一个分隔符的位置
                    strResult = strResult.Mid(pos + 2);
                    // 重新获取分隔符的位置
                    pos = strResult.Find(_T("\r\n"));
                }
                // 处理最后一个子串

                if (!strResult.IsEmpty())
                {
                    if (strResult.GetAt(strResult.GetLength() - 1) == _T('/'))
                    {
                        dirVec.push_back(strRemote + strResult);
                    }
                    fileList.push_back(strRemote + strResult);
                }
            }
            else
            {
                fileList.push_back(strRemote + strResult);
            }
            // 对于每个子目录,进行递归调用

            for (auto entry : dirVec)
            {
                string strFtp = ftpUrl;
                string strEntry = (LPCSTR)(CStringA)(entry);
                strEntry += +"/";
                string subDirUrl = strFtp + strEntry;
                GetFtpDirectoryList(subDirUrl.c_str(), username, password, strEntry.c_str(), fileList);
            }
        }
        else
        {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        }

        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }

    curl_global_cleanup();

    return (res == CURLE_OK);
}

CPP

具体调用函数为:

C++
static void ADSKMyGroupTEST() {

        //const char* ftpServer = "ftp://127.0.0.1:21/";
        //const char* ftpUsername = "ftp";
        //const char* ftpPassword = "ftp";

        CString strFtpSerVer = CUtility::getValueByKey(INI_SETTING_FTPSETTING, INI_NODE_FTPSERVER);
        CString ftpServer = _T("ftp://") + strFtpSerVer;
        CString ftpUsername = CUtility::getValueByKey(INI_SETTING_FTPSETTING, INI_NODE_FTPUSER);
        CString ftpPassword = CUtility::getValueByKey(INI_SETTING_FTPSETTING, INI_NODE_FTPPASSWD);
        CString strLocal = CUtility::getValueByKey(INI_SETTING_FTPSETTING, INI_NODE_FTPLOCALPATH);
        std::vector<CString> allFileList;

        GetFtpDirectoryList((LPCSTR)(LPCTSTR)ftpServer, (LPCSTR)(LPCTSTR)ftpUsername, (LPCSTR)(LPCTSTR)ftpPassword, "", allFileList);

        FtpManage ftp;
        ftp.ConnectFtp();
        for (const auto& item : allFileList)
        {
            CString localPath = strLocal + item;  // 设置本地存储路径

            if (localPath.Find(_T(".")) < 0)  // 如果是目录
            {
                ::CreateDirectory(localPath, NULL);
            }
            else  // 如果是文件
            {
                CString ftpFilePath = _T("/") + item;
                string outputfile = (LPCSTR)(CStringA)(localPath);
                ftp.GetFileFromFtp(ftpFilePath, localPath);
            }
        }
        ftp.CloseFtpConnect();
    }

CPP

从ftp下载文件

ftpmanage.h

C++
#pragma once
#include <afxinet.h>
#include <vector>
using namespace std;

//对 ftp文件进行下载及相关的操作类
class FtpManage
{
public:
    FtpManage();
    ~FtpManage();
private:
    void InitFtpSetting();

    CString m_strFTPServer;//ftp服务器
    CString m_strFTPPassive;//passive标记
    CString m_strFTPRoot;//ftp根目录
    CString m_strFTPUser;//ftp账号
    CString m_strFTPPassWd;//ftp密码

    CInternetSession* m_pInetSession;
    CFtpConnection* m_pFtpConnection;
    vector<CString> getSplitStringVector(CString strFtpPath, LPCTSTR param2 = _T("/"));
public:


    int ConnectFtp();

    //从ftp下载文件
    int GetFileFromFtp(/*CString strFtpPath, */CString strFtpFileName, CString strDwgSavePath);

    //上传文件到ftp
    int PutFileToFtp(CString strLocalFilePath, CString strFtpPath);
    int PutFileToFtpEx(CString strLocalFilePath, CString strFtpPath, CString strFtpFileName);

    //分级设置ftp dir 
    int SetCurrentFtpDir(CString strFtpPath);

    //关闭ftp连接
    int CloseFtpConnect();
    //获取ftp目录中的所有文件//获取中文文件名乱码,不可用
    vector<CString> getAllFileFromFtpServer();
};

CPP

ftpmanage.cpp

C++
#include "stdafx.h"
#include "FtpManage.h"
#include <xlocbuf>
#include <codecvt>

FtpManage::FtpManage():m_pInetSession(NULL),m_pFtpConnection(NULL)
{
    InitFtpSetting();
}

FtpManage::~FtpManage()
{

}

void FtpManage::InitFtpSetting()
{
    m_strFTPServer = CUtility::getValueByKey(INI_SETTING_FTPSETTING, INI_NODE_FTPSERVER);
    m_strFTPPassive = CUtility::getValueByKey(INI_SETTING_FTPSETTING, INI_NODE_FTPPASSIVE);
    m_strFTPRoot = CUtility::getValueByKey(INI_SETTING_FTPSETTING, INI_NODE_FTPROOT);
    m_strFTPUser = CUtility::getValueByKey(INI_SETTING_FTPSETTING, INI_NODE_FTPUSER);
    m_strFTPPassWd = CUtility::getValueByKey(INI_SETTING_FTPSETTING, INI_NODE_FTPPASSWD);
}

std::vector<CString> FtpManage::getSplitStringVector(CString strFtpPath, LPCTSTR param2 /*= _T("/")*/)
{
    vector<CString> retVec;
    retVec.clear();
    int nFind = strFtpPath.Replace(_T("/"), _T("/"));
    if (nFind <= 0)
    {
        retVec.push_back(_T("/"));
        return retVec;
    }
    for (int i=0; i<=nFind; i++)
    {
        retVec.push_back(CUtility::SubString(strFtpPath, _T("/"), i) + _T("/"));
    }
    return retVec;
}

int FtpManage::GetFileFromFtp(/*CString strFtpPath, */CString strFtpFileName, CString strDwgSavePath)
{
    //if (SetCurrentFtpDir(strFtpPath)<0)
    //{
    //  return -1;
    //}
    CFtpFileFind findFile(m_pFtpConnection);
    if (findFile.FindFile(strFtpFileName, INTERNET_FLAG_DONT_CACHE))
    {
        if (!m_pFtpConnection->GetFile(strFtpFileName,strDwgSavePath, FALSE, FILE_ATTRIBUTE_NORMAL, FTP_TRANSFER_TYPE_BINARY, 1))
        {
            DWORD dw = GetLastError();
            CString sError;
            AfxMessageBox(_T("ftp getfile error :%d"), dw);
            return -3;
        }
    }
    else
    {
        return -2;
    }

    return 0;
}

int FtpManage::ConnectFtp()
{
    CWaitCursor wait;

    CString m_sDomainName(m_strFTPServer);
    CString m_ftpUser(m_strFTPUser);
    CString m_ftpPassword(m_strFTPPassWd);

    m_pFtpConnection = NULL;
    m_pInetSession = new CInternetSession(_T("ESAPP"), 1, PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, INTERNET_FLAG_DONT_CACHE);
    if (!m_pInetSession)
    {
        return -1;
    }

    CString strFtpSite = m_sDomainName;
    CString strServerName;
    CString strObject;
    INTERNET_PORT nPort;
    DWORD dwServiceType;

    //检查URL是否正确
    if (!AfxParseURL(strFtpSite, dwServiceType, strServerName, strObject, nPort) || dwServiceType == AFX_INET_SERVICE_UNK)
    {
        CString strFtpURL = _T("ftp://");
        strFtpURL += strFtpSite;

        if (!AfxParseURL(strFtpURL, dwServiceType, strServerName, strObject, nPort))
        {
            return -2;
        }
    }

    if ((dwServiceType == INTERNET_SERVICE_FTP) && !strServerName.IsEmpty())
    {
        try
        {
            //AfxMessageBox(strServerName + _T("\r") + m_ftpUser + _T("\r") + m_ftpPassword);
            if (m_strFTPPassive == _T("TRUE"))
            {
                m_pFtpConnection = m_pInetSession->GetFtpConnection(strServerName, m_ftpUser, m_ftpPassword, nPort, TRUE);
            }
            else
            {
                m_pFtpConnection = m_pInetSession->GetFtpConnection(strServerName, m_ftpUser, m_ftpPassword, nPort, FALSE);
            }
        }
        catch (CInternetException* pEx)
        {
            CString strInteError = _T("");
            TCHAR szErr[1024];
            if (pEx->GetErrorMessage(szErr, 1024))
            {
                strInteError.Format(_T("%s"), szErr);
                pEx->Delete();
            }
            AfxMessageBox(strInteError);
            return -3;
        }
    }
    return 0;
}

int FtpManage::PutFileToFtp(CString strLocalFilePath, CString strFtpPath)
{
    CString sFileName;
    int nFind = strLocalFilePath.ReverseFind(_T('\\'));
    sFileName = strLocalFilePath.Mid(nFind+1);

    return PutFileToFtpEx(strLocalFilePath, strFtpPath, sFileName);
}

int FtpManage::PutFileToFtpEx(CString strLocalFilePath, CString strFtpPath, CString strFtpFileName)
{
    int nRes = SetCurrentFtpDir(strFtpPath);
    if (nRes!=0)
    {
        return -1;
    }
    CFtpFileFind findFile(m_pFtpConnection);
    if (findFile.FindFile(strFtpFileName,INTERNET_FLAG_DONT_CACHE))
    {
        m_pFtpConnection->Remove(strFtpFileName);
    }
    if (!m_pFtpConnection->PutFile(strLocalFilePath,strFtpFileName))
    {
        DWORD dw = GetLastError();
        int nError = (int)dw;
        CString strInterError;
        strInterError.Format(_T("%d"), nError);
        AfxMessageBox(strInterError);
        return -2;
    }
    return 0;
}

int FtpManage::SetCurrentFtpDir(CString strFtpPath)
{
    if (m_pFtpConnection==NULL)
    {
        return -1;
    }
    //会存在多级 然后一次设置下去 如果失败了 就返回问题
    strFtpPath.Replace(_T("\\"), _T("/"));

    vector<CString> vecCatalogue;
    //gMyString.Split(strFtpPath, _T("/"), vecCatalogue);
    vecCatalogue = getSplitStringVector(strFtpPath, _T("/"));
    for (int i=0;i<vecCatalogue.size();i++)
    {
        CString sTempCatalogue = vecCatalogue[i];
        if (sTempCatalogue==_T(""))
        {
            continue;
        }
        if (!m_pFtpConnection->SetCurrentDirectory(sTempCatalogue))
        {
            if (!m_pFtpConnection->CreateDirectory(sTempCatalogue))
            {
                return -2;
            }
            if (!m_pFtpConnection->SetCurrentDirectory(sTempCatalogue))
            {
                return -3;
            }
        }
    }
    return 0;
}

int FtpManage::CloseFtpConnect()
{
    if (m_pFtpConnection!=NULL)
    {
        m_pFtpConnection->Close();
        delete m_pFtpConnection;
        m_pFtpConnection = NULL;
    }
    if (m_pInetSession!=NULL)
    {
        m_pInetSession->Close();
        delete m_pInetSession;
        m_pInetSession = NULL;
    }
    return 0;
}
wchar_t * ANSIToUnicode(const char* str)
{
    int textlen;
    wchar_t * result;
    textlen = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
    result = (wchar_t *)malloc((textlen + 1) * sizeof(wchar_t));
    memset(result, 0, (textlen + 1) * sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, 0, str, -1, (LPWSTR)result, textlen);
    return result;
}

//获取中文文件名乱码
std::vector<CString> FtpManage::getAllFileFromFtpServer()
{
    vector<CString> tmpVec;
    tmpVec.clear();
    if (SetCurrentFtpDir(m_strFTPServer) < 0)
    {
        return tmpVec;
    }
    try
    {
        // use a file find object to enumerate files
        CFtpFileFind findFile(m_pFtpConnection);
        CString strName, strDirectory;
        m_pFtpConnection->GetCurrentDirectory(strDirectory);
        // start looping
        BOOL bWorking = findFile.FindFile(_T("*"));

        //while (bWorking)
        //{
        //  bWorking = findFile.FindNextFile();
        //  tmpVec.push_back(findFile.GetFileURL());
        //  //_tprintf_s(_T("%s\n"), (LPCTSTR)findFile.GetFileURL());
        //}

        BOOL bFind = findFile.FindFile(_T("/"), INTERNET_FLAG_EXISTING_CONNECT);
        bool flag = false;
        while (bFind)
        {
            bFind = findFile.FindNextFile();

            if (findFile.IsDots())
            {
                continue;
            }
            CString remoteFileName = findFile.GetFileName();
            // 转换为 UTF-8 编码
            std::string fileNameUtf8 = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(findFile.GetFileName());

            CString strName = fileNameUtf8.c_str();

    /*      CString remoteFilePath = remoteDir + remoteFileName;
            CString localFilePath = localDir + remoteFileName;*/
            //flag = 1为获取目录下的子文件,flag = 0为获取当前文件夹下的所有子文件。
            if (flag)
            {
                if (findFile.IsDirectory())
                {
                    // 如果是目录,递归下载其中的文件和子目录
                    //CreateDirectory(localFilePath, nullptr);

                    strDirectory = strDirectory + _T("/") + strName;
                    tmpVec.push_back(strName);
                }
            }
            else
            {
                tmpVec.push_back(strName);
            }
        }

        findFile.Close();
    }
    catch (CInternetException* pEx)
    {
        TCHAR sz[1024];
        pEx->GetErrorMessage(sz, 1024);
        _tprintf_s(_T("ERROR!  %s\n"), sz);
        pEx->Delete();
    }
    return tmpVec;
}

保存标记

DBMOD,只读

  • //声明设置数据库模式的函数
C++
extern long acdbSetDbmod(AcDbDatabase * pDb, long newVal); 
  • 另外还有方法的,AcApDocment类有两个成员接口,pushDbmod和popDbmod

将子目录中的所有文件拷贝到子目录中并添加-

先遍历子目录中所有符合要求的文件

Python
def get_files_in_directory(directory, fileension):
    # 创建一个字典来存储目录和文件名
    directory_map = {}

    # 遍历目录及其子目录
    for root, dirs, files in os.walk(directory):
        # 将当前目录下的所有文件名添加到字典中
        for file in files:
            if file.endswith(fileension):
                # 获取当前目录名
                fileName = os.path.join(root, file)
                current_dir = root.replace(path, "")
                # current_dir = re.sub(r'\\', '-',os.path.dirname(fileName))
                current_dir = re.sub(r"\\", "-", current_dir)
                # 如果当前目录名不在字典中,则添加它
                if current_dir not in directory_map:
                    directory_map[current_dir] = []
                directory_map[current_dir].append(file)

    return directory_map

将目录和文件名获取后进行拆解

Python
def get_special_file(directory_map, isCopy=False):
    """
    处理特殊文件。

    根据提供的目录映射字典,对每个文件进行处理。如果指定复制,则将文件从原始位置复制到新位置。

    参数:
        directory_map (dict): 一个字典,键为目录名,值为该目录下的文件列表。
        isCopy (bool): 是否复制文件,默认为False。

    返回:
        list: 包含处理过的文件名的列表。
    """
    # 创建一个列表来存储处理过的文件名
    fileNameList = []
    # 遍历目录映射字典中的每个目录和文件
    for directory, files in directory_map.items():
        for file in files:
            # 排除空目录
            if directory != "":
                # 如果目录名末尾没有"-",则添加之
                if directory[-1] != "-":
                    directory += "-"
                # 组合得到文件的完整名
                svgName = directory + file
                # 准备文件的源路径和目标路径
                preSvgName = path + directory.replace("-", "\\") + file
                # 将文件名(不包含扩展名)添加到列表中
                fileNameList.append(svgName.split(".")[0])
                # 准备文件的新路径
                newSvgName = path + svgName
                # 如果指定复制文件,则执行复制操作
                if isCopy:
                    os.system(f"copy {preSvgName} {newSvgName}")

    # 返回处理过的文件名列表
    return fileNameList

将信息写入json

Python
1
2
3
4
5
6
7
 # 将filenameList写入list.json文件,key值为filename
    final_dict = {"data": [{"name": fileName} for fileName in fileNameList]}
    # 转换为 JSON
    json_string = json.dumps(final_dict, ensure_ascii=False)
    with open(f"{path}\\list.json", "w", encoding="utf-8") as file:
        file.write(json_string)
    print(f"{path}\\list.json")

完整的代码如下所示

Python
# 获取目录下所有的dwg文件名和文件路径
import os
import re
import sys
import json


def get_files_in_directory(directory, fileension):
    # 创建一个字典来存储目录和文件名
    directory_map = {}

    # 遍历目录及其子目录
    for root, dirs, files in os.walk(directory):
        # 将当前目录下的所有文件名添加到字典中
        for file in files:
            if file.endswith(fileension):
                # 获取当前目录名
                fileName = os.path.join(root, file)
                current_dir = root.replace(path, "")
                # current_dir = re.sub(r'\\', '-',os.path.dirname(fileName))
                current_dir = re.sub(r"\\", "-", current_dir)
                # 如果当前目录名不在字典中,则添加它
                if current_dir not in directory_map:
                    directory_map[current_dir] = []
                directory_map[current_dir].append(file)

    return directory_map


# 获取当前脚本目录
def get_current_file_path():
    # 通过命令行参数获取当前脚本的绝对路径
    abs_file = sys.argv[0]
    # 将路径中的斜杠替换为反斜杠,以适应Windows系统
    windows_path = abs_file.replace("/", "\\")
    # 去除路径中的脚本文件名,仅保留目录部分
    windows_path = windows_path[: windows_path.rfind("\\")]
    # 返回脚本所在的目录路径
    return windows_path


def get_special_file(directory_map, isCopy=False):
    """
    处理特殊文件。

    根据提供的目录映射字典,对每个文件进行处理。如果指定复制,则将文件从原始位置复制到新位置。

    参数:
        directory_map (dict): 一个字典,键为目录名,值为该目录下的文件列表。
        isCopy (bool): 是否复制文件,默认为False。

    返回:
        list: 包含处理过的文件名的列表。
    """
    # 创建一个列表来存储处理过的文件名
    fileNameList = []
    # 遍历目录映射字典中的每个目录和文件
    for directory, files in directory_map.items():
        for file in files:
            # 排除空目录
            if directory != "":
                # 如果目录名末尾没有"-",则添加之
                if directory[-1] != "-":
                    directory += "-"
                # 组合得到文件的完整名
                svgName = directory + file
                # 准备文件的源路径和目标路径
                preSvgName = path + directory.replace("-", "\\") + file
                # 将文件名(不包含扩展名)添加到列表中
                fileNameList.append(svgName.split(".")[0])
                # 准备文件的新路径
                newSvgName = path + svgName
                # 如果指定复制文件,则执行复制操作
                if isCopy:
                    os.system(f"copy {preSvgName} {newSvgName}")

    # 返回处理过的文件名列表
    return fileNameList


if __name__ == "__main__":
    print(
        """
        fileension: \033[34mdwg,dxf, svg,pdf,bmp,png\033[0m等等
        isCopy: 是否复制文件到当前目录
        获取目录下所有的dwg文件名和文件路径
        """
    )
    # path = get_current_file_path()
    # if path is None:
    path = "E:\\Gitee\\vue\\gallery\\Gallery\\src\\assets\\icons\\"
    # 如果path最后不带\\结尾,则添加\\
    if path[-1] != "\\":
        path += "\\"
    print(path)
    isCopy = input("是否复制文件到当前目录?(y/n)")
    if isCopy == "y":
        isCopy = True
    else:
        isCopy = False
    fileension = input("请输入文件后缀名:")
    if fileension == "":
        fileension = ".svg"

    if fileension[0] != ".":
        fileension = "." + fileension

    directory_map = get_files_in_directory(path, fileension)
    fileNameList = get_special_file(directory_map, isCopy)

    # 将filenameList写入list.json文件,key值为filename
    final_dict = {"data": [{"name": fileName} for fileName in fileNameList]}
    # 转换为 JSON
    json_string = json.dumps(final_dict, ensure_ascii=False)
    with open(f"{path}\\list.json", "w", encoding="utf-8") as file:
        file.write(json_string)
    print(f"{path}\\list.json")