Browse Source

CorelDRAW-CPG C++ 编程傻瓜入门文档 和 智能群组项目

Hongwenjun 6 months ago
parent
commit
f7139e5e7c

BIN
08_SmartGroup/Makefile


+ 261 - 0
08_SmartGroup/ToolsBox.cpp

@@ -0,0 +1,261 @@
+#include <stdio.h>
+#include <windows.h>
+#include "cdrapi.h"
+#include "resource.h"
+#include "cdrapp.h"
+
+corel *cdr = NULL;
+static HINSTANCE g_hResource = NULL;
+
+BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    if (fdwReason == DLL_PROCESS_ATTACH) {
+        g_hResource = (HINSTANCE)hinstDLL;
+    }
+    return TRUE;
+}
+
+class ToolsBoxPlugin : public VGCore::IVGAppPlugin
+{
+private:
+
+    volatile ULONG m_ulRefCount;
+    long m_lCookie;
+
+    static INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+    void OpenToolsBox();
+
+
+public:
+    ToolsBoxPlugin();
+    VGCore::IVGApplication* m_pApp;
+
+// IUnknown
+public:
+    STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
+    STDMETHOD_(ULONG, AddRef)(void) { return ++m_ulRefCount; }
+    STDMETHOD_(ULONG, Release)(void)
+    {
+        ULONG ulCount = --m_ulRefCount;
+        if (ulCount == 0) {
+            delete this;
+        }
+        return ulCount;
+    }
+
+// IDispatch
+public:
+    STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) { return E_NOTIMPL; }
+    STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { return E_NOTIMPL; }
+    STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { return E_NOTIMPL; }
+    STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr);
+
+// IVGAppPlugin
+public:
+    STDMETHOD(raw_OnLoad)(VGCore::IVGApplication* Application);
+    STDMETHOD(raw_StartSession)();
+    STDMETHOD(raw_StopSession)();
+    STDMETHOD(raw_OnUnload)();
+
+};
+
+ToolsBoxPlugin::ToolsBoxPlugin()
+{
+    m_pApp = NULL;
+    m_lCookie = 0;
+    m_ulRefCount = 1;
+}
+
+STDMETHODIMP ToolsBoxPlugin::QueryInterface(REFIID riid, void** ppvObject)
+{
+    HRESULT hr = S_OK;
+    m_ulRefCount++;
+    if (riid == IID_IUnknown) {
+        *ppvObject = (IUnknown*)this;
+    } else if (riid == IID_IDispatch) {
+        *ppvObject = (IDispatch*)this;
+    } else if (riid == __uuidof(VGCore::IVGAppPlugin)) {
+        *ppvObject = (VGCore::IVGAppPlugin*)this;
+    } else {
+        m_ulRefCount--;
+        hr = E_NOINTERFACE;
+    }
+    return hr;
+}
+
+STDMETHODIMP ToolsBoxPlugin::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
+{
+    switch (dispIdMember) {
+
+    case 0x0014: // DISPID_APP_ONPLUGINCMD
+        if (pDispParams != NULL && pDispParams->cArgs == 1) {
+            _bstr_t strCmd(pDispParams->rgvarg[0].bstrVal);
+            if (strCmd == _bstr_t("OpenToolsBox")) {
+                //   MessageBox(NULL, _bstr_t("OpenToolsBox"), _bstr_t("OpenToolsBox"), MB_ICONSTOP);
+                OpenToolsBox();
+            }
+        }
+        break;
+
+    case 0x0015: // DISPID_APP_ONPLUGINCMDSTATE
+        if (pDispParams != NULL && pDispParams->cArgs == 3) {
+            _bstr_t strCmd(pDispParams->rgvarg[2].bstrVal);
+            if (strCmd == _bstr_t("OpenToolsBox")) {
+                *pDispParams->rgvarg[1].pboolVal = VARIANT_TRUE;
+            }
+        }
+        break;
+    }
+    return S_OK;
+}
+
+STDMETHODIMP ToolsBoxPlugin::raw_OnLoad(VGCore::IVGApplication* Application)
+{
+    m_pApp = Application;
+    if (m_pApp) {
+        m_pApp->AddRef();
+    }
+    return S_OK;
+}
+
+STDMETHODIMP ToolsBoxPlugin::raw_StartSession()
+{
+    // 接口转交给cdr
+    cdr = m_pApp;
+
+    try {
+        m_pApp->AddPluginCommand(_bstr_t("OpenToolsBox"), _bstr_t("Tools Box"), _bstr_t("打开工具窗口"));
+
+        VGCore::ICUIControlPtr ctl = m_pApp->CommandBars->Item[_bstr_t("Standard")]->Controls->AddCustomButton(VGCore::cdrCmdCategoryPlugins, _bstr_t("OpenToolsBox"), 10, VARIANT_FALSE);
+        ctl->SetIcon2(_bstr_t("guid://d2fdc0d9-09f8-4948-944c-4297395c05b7"));
+        m_lCookie = m_pApp->AdviseEvents(this);
+    } catch (_com_error &e) {
+        MessageBox(NULL, e.Description(), _bstr_t("Error"), MB_ICONSTOP);
+    }
+    return S_OK;
+}
+
+STDMETHODIMP ToolsBoxPlugin::raw_StopSession()
+{
+    try {
+        m_pApp->UnadviseEvents(m_lCookie);
+        m_pApp->RemovePluginCommand(_bstr_t("OpenToolsBox"));
+    } catch (_com_error &e) {
+        MessageBox(NULL, e.Description(), _bstr_t("Error"), MB_ICONSTOP);
+    }
+    return S_OK;
+}
+
+STDMETHODIMP ToolsBoxPlugin::raw_OnUnload()
+{
+    if (m_pApp) {
+        m_pApp->Release();
+        m_pApp = NULL;
+    }
+    return S_OK;
+}
+
+void ToolsBoxPlugin::OpenToolsBox()
+{
+    m_pApp->StartupMode = VGCore::cdrStartupDoNothing;
+
+    INT_PTR nHandle = m_pApp->AppWindow->Handle;
+    HWND hAppWnd = reinterpret_cast<HWND>(nHandle);
+
+    // 创建非模态对话框
+    HWND hDlgWnd = CreateDialogParam(g_hResource, MAKEINTRESOURCE(IDD_TOOLS_BOX), hAppWnd, DlgProc, (LPARAM)m_pApp);
+    // 在创建对话框之前存储 m_pApp 指针
+    SetWindowLongPtr(hDlgWnd, DWLP_USER, (LONG_PTR)m_pApp);
+
+    // 获取屏幕的宽度和高度
+    RECT rect;
+    GetWindowRect(GetDesktopWindow(), &rect);
+    int screenWidth = rect.right - rect.left;
+    int screenHeight = rect.bottom - rect.top;
+
+    // 计算对话框窗口的宽度和高度
+    RECT dlgRect;
+    GetWindowRect(hDlgWnd, &dlgRect);
+    int dlgWidth = dlgRect.right - dlgRect.left;
+    int dlgHeight = dlgRect.bottom - dlgRect.top;
+
+    // 计算对话框窗口的左上角坐标,使其居中显示
+    int x = (screenWidth - dlgWidth) / 2;
+    int y = (screenHeight - dlgHeight) / 2;
+
+    // 设置对话框窗口的位置
+    SetWindowPos(hDlgWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+    // 设置对话框窗口的父窗口  // #define GWL_HWNDPARENT      (-8)
+    SetWindowLong(hDlgWnd, -8, (LONG)hAppWnd);
+    // 显示对话框窗口
+    ShowWindow(hDlgWnd, SW_SHOW);
+}
+
+
+INT_PTR CALLBACK ToolsBoxPlugin::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    // 从附加数据中获取 m_pApp 指针
+    VGCore::IVGApplication* cdr = reinterpret_cast<VGCore::IVGApplication*>(GetWindowLongPtr(hDlg, DWLP_USER));
+
+    if (uMsg == WM_COMMAND) {
+        try {
+            switch (LOWORD(wParam)) {
+            case IDC_RED :
+                Box_AutoGroup(cdr);
+
+                MessageBox(NULL, "方框智能群组:Union-Find 算法\n 分组记录请查看: D:\\group.txt", "CPG代码测试", MB_ICONSTOP);
+                Active_CorelWindows(hDlg);
+                break;
+
+            case IDC_CQL_OUTLINE:
+                cql_OutlineColor(cdr);
+                Active_CorelWindows(hDlg);
+                break;
+
+            case IDC_CQL_FILL:
+                cql_FillColor(cdr);
+                Active_CorelWindows(hDlg);
+                break;
+
+            case IDC_CQL_SIZE:
+                cql_SameSize(cdr);
+                Active_CorelWindows(hDlg);
+                break;
+
+            case IDC_CLEAR_FILL:
+                Clear_Fill(cdr);
+                break;
+
+            case IDC_SR_FLIP:
+                Shapes_Filp(cdr);
+                break;
+
+            case IDC_CDR2AI:
+                CdrCopy_to_AdobeAI(cdr);
+                break;
+
+            case IDC_AI2CDR:
+                AdobeAI_Copy_ImportCdr(cdr);
+                break;
+
+            case IDOK:
+            case IDCANCEL:
+                EndDialog(hDlg, 0);
+                break;
+            }
+
+        } catch (_com_error &e) {
+            MessageBox(NULL, e.Description(), "Error", MB_ICONSTOP);
+        }
+
+    } else if (uMsg == WM_INITDIALOG) {
+        return 1;
+    }
+    return 0;
+}
+
+extern "C" __declspec(dllexport) DWORD APIENTRY AttachPlugin(VGCore::IVGAppPlugin** ppIPlugin)
+{
+    *ppIPlugin = new ToolsBoxPlugin;
+    return 0x100;
+}

+ 40 - 0
08_SmartGroup/ToolsBox.rc

@@ -0,0 +1,40 @@
+// Generated by ResEdit 1.6.6
+// Copyright (C) 2006-2015
+// http://www.resedit.net
+
+#include <windows.h>
+#include <commctrl.h>
+#include <richedit.h>
+#include "resource.h"
+
+
+
+
+//
+// Bitmap resources
+//
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDB_BITMAP1        BITMAP         ".\\cpg.bmp"
+
+
+
+//
+// Dialog resources
+//
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+IDD_TOOLS_BOX DIALOGEX 0, 0, 136, 226
+STYLE DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_POPUP | WS_SYSMENU
+CAPTION "Tools Box"
+FONT 8, "MS Shell Dlg", 400, 0, 1
+{
+    LTEXT           "蘭雅 CorelDRAW CPG 插件 2024.8.6 智能群组版", 0, 18, 120, 97, 18, SS_LEFT, WS_EX_LEFT
+    CONTROL         IDB_BITMAP1, 0, WC_STATIC, SS_BITMAP, 1, 149, 133, 75, WS_EX_LEFT
+    PUSHBUTTON      "方框智能群组", IDC_RED, 73, 3, 59, 24, 0, WS_EX_LEFT
+    PUSHBUTTON      "CQL轮廓色相同", IDC_CQL_OUTLINE, 5, 2, 59, 24, 0, WS_EX_LEFT
+    PUSHBUTTON      "无填色", IDC_CLEAR_FILL, 73, 30, 59, 24, 0, WS_EX_LEFT
+    PUSHBUTTON      "批量镜像", IDC_SR_FLIP, 73, 58, 59, 24, 0, WS_EX_LEFT
+    PUSHBUTTON      "CQL颜色相同", IDC_CQL_FILL, 5, 30, 59, 24, 0, WS_EX_LEFT
+    PUSHBUTTON      "CQL尺寸相同", IDC_CQL_SIZE, 5, 58, 59, 24, 0, WS_EX_LEFT
+    PUSHBUTTON      "CDR复制到AI", IDC_CDR2AI, 5, 86, 59, 24, 0, WS_EX_LEFT
+    PUSHBUTTON      "AI粘贴到CDR", IDC_AI2CDR, 73, 86, 59, 24, 0, WS_EX_LEFT
+}

+ 39 - 0
08_SmartGroup/VBA_GMS/VbaCallCPG.bas

@@ -0,0 +1,39 @@
+Attribute VB_Name = "VbaCallCPG"
+Private Declare PtrSafe Function vbadll Lib "C:\Program Files\Corel\CorelDRAW Graphics Suite 2020\Draw\Plugins64\lycpg64.cpg" (ByVal code As Long) As Long
+
+Sub VBA调用CPG_CDR复制物件到AI()
+ ret = vbadll(2)
+ MsgBox "CDR复制物件到AI 功能 " & ret
+End Sub
+
+Sub AI复制物件到CDR()
+ ret = vbadll(1)
+ MsgBox "AI复制物件到CDR 功能 " & ret
+End Sub
+
+Sub Clear_Fill()
+ ret = vbadll(3)
+ MsgBox "Clear_Fill功能 " & ret
+End Sub
+
+
+Sub cql_FillColor()
+ ret = vbadll(5)
+End Sub
+
+
+Sub Shapes_Filp()
+ ret = vbadll(4)
+End Sub
+
+Sub cql_OutlineColor()
+ ret = vbadll(6)
+End Sub
+
+Sub cql_SameSize()
+ ret = vbadll(7)
+End Sub
+
+Sub fill_red()
+ ret = vbadll(8)
+End Sub

+ 6 - 0
08_SmartGroup/VBA_GMS/使用视频.txt

@@ -0,0 +1,6 @@
+【蘭雅 CorelDRAW CPG 插件:  VBA 调用 C++ cpg 插件,达到加密和简单做界面的效果】 
+
+https://www.bilibili.com/video/BV1cZ421T7u7
+
+VBA GMS 调用 CPG源码:
+VbaCallCPG.bas  

+ 175 - 0
08_SmartGroup/boxAutoGroup.cpp

@@ -0,0 +1,175 @@
+#include "cdrapp.h"
+#include <algorithm>
+#include <map>
+#include <vector>
+#include <iostream>
+#include <fstream>
+#include <chrono>
+
+#define GET_BOUNDING_BOX(box)                                                  \
+  GetBoundingBox(&(box).x, &(box).y, &(box).w, &(box).h, false)
+
+#define ZERO_4PC 0, 0, 0, 0
+
+typedef struct {
+  double x; // 左下角 x 坐标
+  double y; // 左下角 y 坐标
+  double w; // 宽度
+  double h; // 高度
+} BoundingBox;
+
+double get_bounding_box_area(BoundingBox box) { return box.w * box.h; }
+
+// 自定义比较函数,按 BoundingBox 的面积大小进行排序
+bool compare_bounding_boxes(const std::pair<int, BoundingBox> &a,
+                            const std::pair<int, BoundingBox> &b) {
+  return get_bounding_box_area(a.second) > get_bounding_box_area(b.second);
+}
+
+// 查找父节点
+int find(std::vector<int>& parent, int x) {
+    if (parent[x] != x) {
+        parent[x] = find(parent, parent[x]);
+    }
+    return parent[x];
+}
+
+// 合并两个集合
+void unionSet(std::vector<int>& parent, int x, int y) {
+    int xroot = find(parent, x);
+    int yroot = find(parent, y);
+    parent[xroot] = yroot;
+}
+// 检查两个矩形是否重叠
+bool isOverlapped(const BoundingBox &a, const BoundingBox &b) {
+  return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
+} // 函数使用AABB(Axis-Aligned Bounding Box)碰撞检测
+
+bool BBox_DrawRectangle(corel *cdr) {
+  BoundingBox box;
+  auto sr = cdr->ActiveSelectionRange; // 获得选择范围
+  auto al = cdr->ActiveLayer;          // 获得当前层
+  if (!sr || !al) return false;
+
+  // CorelDRAW Shapes 物件 Item 编号从1开始
+  for (auto i = 0; i != sr->Count; i++) {
+    sr->Shapes->Item[i + 1]->GET_BOUNDING_BOX(box); // 获得Shapes的BoundingBox,赋值到box
+    al->CreateRectangle2(box.x, box.y, box.w, box.h, ZERO_4PC); // 使用BoundingBox box 创建一个矩形
+  }
+  return true;
+}
+
+
+#include <thread>
+#include <mutex>
+
+std::mutex mtx; // 用于保护共享资源
+
+void groupShapes(std::vector<int> shapes, IVGShapeRangePtr srgp, IVGShapeRangePtr sr) {
+    for (int index : shapes) {
+        srgp->Add(sr->Shapes->Item[index]);
+    }
+    if (shapes.size() > 1) {
+        // 这里需要锁定,以防止多线程访问冲突
+        mtx.lock();
+        srgp->Group();
+        mtx.unlock();
+    }
+    srgp->RemoveAll();
+}
+
+void processGroups(std::map<int, std::vector<int>> groups, corel* cdr , IVGShapeRangePtr sr) {
+    std::vector<std::thread> threads;
+
+    for (const auto& group : groups) {
+
+        auto srgp = cdr->CreateShapeRange();
+
+        // 启动线程处理每个分组
+        threads.emplace_back(groupShapes, group.second, srgp, sr);
+    }
+
+    // 等待所有线程完成
+    for (auto& thread : threads) {
+        if (thread.joinable()) {
+            thread.join();
+        }
+    }
+}
+
+
+// 快速分组重叠的区域, 使用算法"Union-Find" 算法。这个算法可以有效地处理这种并集问题。
+// 算法的时间复杂度为 O(n^2),其中 n 是矩形的数量。如果矩形数量较多,可以考虑使用更高效的算法,
+// 例如使用四叉树(Quadtree)或者区间树(Interval Tree)等数据结构来加速计算。
+bool Box_AutoGroup(corel *cdr) {
+  BoundingBox box;
+
+  auto sr = cdr->ActiveSelectionRange; // 获得选择范围
+  auto al = cdr->ActiveLayer;          // 获得当前层
+  if (!sr || !al) return false;
+
+  auto start = std::chrono::high_resolution_clock::now(); // 开始时间
+  BeginOpt(cdr);
+
+  std::vector<BoundingBox> boxes;
+  std::vector<int> parent;
+
+  // CorelDRAW Shapes 物件 Item 编号从1开始
+  for (auto i = 0; i != sr->Count; i++) {
+    sr->Shapes->Item[i + 1]->GET_BOUNDING_BOX(box);
+    boxes.push_back(box);
+    parent.push_back(i);
+  }
+
+  // 实现 Union-Find 算法来合并重叠的区域
+  for (int i = 0; i < boxes.size(); i++) {
+    for (int j = i + 1; j < boxes.size(); j++) {
+      if (isOverlapped(boxes[i], boxes[j])) {
+        unionSet(parent, i, j);
+      }
+    }
+  }
+
+ // 输出分组结果到文件
+  std::ofstream output_file("D:\\group.txt");
+  if (output_file.is_open()) {
+      std::map<int, std::vector<int>> groups;
+      for (int i = 0; i < parent.size(); i++) {
+          int root = find(parent, i);
+          groups[root].push_back(i + 1); // CorelDRAW Shapes 物件 Item 编号从1开始
+      }
+
+      for (const auto& group : groups) {
+          output_file << "Group: ";
+          for (int index : group.second) {
+              output_file << index << " ";
+          }
+          output_file << std::endl;
+      }
+
+    auto end = std::chrono::high_resolution_clock::now(); // 结束时间
+    // 计算持续时间
+    std::chrono::duration<double> duration = end - start;
+    output_file << "Execution time: " << duration.count() << " seconds\n";
+
+    output_file.close();
+  } 
+
+  // 输出分组结果
+  std::map<int, std::vector<int>> groups;
+  for (int i = 0; i < parent.size(); i++) {
+    int root = find(parent, i);
+    groups[root].push_back(i + 1); // CorelDRAW Shapes 物件 Item 编号从1开始
+  }
+
+ // 多线程调用
+  processGroups(groups, cdr, sr);
+
+// https://community.coreldraw.com/sdk/f/coreldraw-and-corel-designer-api/67436/i-am-using-c-to-write-a-cpg-plugin-when-using-shaperange-group-in-coreldraw-to-group-2-000-objects-it-takes-30-seconds
+// 我在使用 C++ 编写CPG 插件,上万个物件重叠分组,C++ 算法速度很快,不到 0.25秒。但是使用 ShapeRange.Group在 CorelDRAW,群组2000个组,速度要30秒。怎么解决软件的瓶颈
+// 我已经使用过窗口刷新优化,调用以上优化函数。现在瓶颈是 ShapeRange.Group 遍历执行2000次,CorelDRAW卡在哪里。是否有能通过多线程,或者SDK调用类似API解决次问题?
+// 多线程调用 ShapeRange.Group() 进行批量群组,好的结果是是程序没有崩溃。坏的结果的并没有提高速度
+
+  EndOpt(cdr);
+  return true;
+}

+ 172 - 0
08_SmartGroup/cdrPDF2Clip.cpp

@@ -0,0 +1,172 @@
+#include "cdrapp.h"
+#include <stdio.h>
+#include <windows.h>
+
+
+#define CUSTOM_FORMAT RegisterClipboardFormatA("Portable Document Format")
+
+bool pdf_to_clipboard(const char *pdffile)
+{
+    // 打开剪贴板
+    if (!OpenClipboard(NULL)) {
+        printf("Failed to open clipboard.\n");
+        return false;
+    }
+
+    // 清空剪贴板
+    EmptyClipboard();
+
+    // 读取PDF文件到内存
+    FILE *file = fopen(pdffile, "rb");
+    if (!file) {
+        printf("Failed to open file.\n");
+        CloseClipboard();
+        return false;
+    }
+
+    // 获取文件大小
+    fseek(file, 0, SEEK_END);
+    size_t fileSize = ftell(file);
+    fseek(file, 0, SEEK_SET);
+
+    // 分配内存并读取文件内容
+    void *pdfData = malloc(fileSize);
+    if (!pdfData) {
+        printf("Failed to allocate memory.\n");
+        fclose(file);
+        CloseClipboard();
+        return false;
+    }
+
+    fread(pdfData, 1, fileSize, file);
+    fclose(file);
+
+    // 将二进制数据写入剪贴板
+    HGLOBAL hGlobal = GlobalAlloc(GHND, fileSize);
+    if (!hGlobal) {
+        printf("Failed to allocate global memory.\n");
+        free(pdfData);
+        CloseClipboard();
+        return false;
+    }
+
+    memcpy(GlobalLock(hGlobal), pdfData, fileSize);
+    GlobalUnlock(hGlobal);
+
+    if (!SetClipboardData(CUSTOM_FORMAT, hGlobal)) {
+        printf("Failed to set clipboard data.\n");
+        GlobalFree(hGlobal);
+        free(pdfData);
+        CloseClipboard();
+        return false;
+    }
+    // 关闭剪贴板
+    CloseClipboard();
+
+    printf("PDF binary data copied to clipboard using custom format.\n");
+    // 不要忘记释放内存
+    free(pdfData);
+    return true;
+}
+
+bool clipboard_to_pdf(const char *outputFile)
+{
+    // 打开剪贴板
+    if (!OpenClipboard(NULL)) {
+        printf("Failed to open clipboard.\n");
+        return false;
+    }
+
+    // 获取剪贴板中的PDF数据
+    HANDLE hData = GetClipboardData(CUSTOM_FORMAT);
+    if (!hData) {
+        printf("Failed to get clipboard data.\n");
+        CloseClipboard();
+        return false;
+    }
+
+    // 锁定内存并获取指针
+    void *pdfData = GlobalLock(hData);
+    if (!pdfData) {
+        printf("Failed to lock global memory.\n");
+        CloseClipboard();
+        return false;
+    }
+
+    // 获取PDF数据的大小
+    size_t fileSize = GlobalSize(hData);
+
+    // 将PDF数据写入文件
+    FILE *file = fopen(outputFile, "wb");
+    if (!file) {
+        printf("Failed to open output file.\n");
+        GlobalUnlock(hData);
+        CloseClipboard();
+        return false;
+    }
+
+    fwrite(pdfData, 1, fileSize, file);
+    fclose(file);
+
+    // 解锁内存并关闭剪贴板
+    GlobalUnlock(hData);
+    CloseClipboard();
+
+    printf("PDF binary data from clipboard saved to file: %s\n", outputFile);
+
+    return true;
+}
+
+bool cdr_savepdf(corel *cdr, const char *outputFile)
+{
+    DeleteFile(_bstr_t(outputFile));
+    auto pdfst = cdr->ActiveDocument->PDFSettings;
+    pdfst->BitmapCompression = pdfLZW;
+    pdfst->ColorMode = pdfCMYK;
+    pdfst->EmbedBaseFonts = cdrFalse;
+    pdfst->EmbedFonts = cdrFalse;
+    pdfst->FileInformation = cdrFalse;
+    pdfst->Hyperlinks = cdrFalse;
+    pdfst->IncludeBleed = cdrFalse;
+    pdfst->Linearize = cdrTrue;
+    pdfst->MaintainOPILinks = cdrTrue;
+    pdfst->Overprints = cdrTrue;
+    pdfst->PutpdfVersion(pdfVersion14); //'pdfVersion14 : pdfVersion13;
+    pdfst->PublishRange = pdfSelection;
+    pdfst->RegistrationMarks = cdrFalse;
+    pdfst->SpotColors = cdrTrue;
+    pdfst->Startup = pdfPageOnly;
+    pdfst->SubsetFonts = cdrFalse;
+    pdfst->TextAsCurves = cdrFalse;
+    pdfst->Thumbnails = cdrFalse;
+    cdr->ActiveDocument->PublishToPDF(_bstr_t(outputFile));
+
+    return true;
+}
+
+void CdrCopy_to_AdobeAI(corel *cdr)
+{
+    char path[MAX_PATH] = {0};
+    GetTempPath(MAX_PATH, path);
+    char *f = strcat(path, "CDR2AI.pdf");
+    if (cdr_savepdf(cdr, f))
+        pdf_to_clipboard(f);
+}
+
+bool pdf_ImportCdr(corel *cdr, const char *pdffile)
+{
+   auto si = cdr->CreateStructImportOptions();
+   si->MaintainLayers = true;
+   
+   auto impflt = cdr->ActiveLayer->ImportEx(_bstr_t(pdffile), cdrAutoSense , si);
+   impflt->Finish();
+}
+
+void AdobeAI_Copy_ImportCdr(corel *cdr)
+{
+    char path[MAX_PATH] = {0};
+    GetTempPath(MAX_PATH, path);
+    char *f = strcat(path, "CDR2AI.pdf");
+    if (clipboard_to_pdf(f))
+        pdf_ImportCdr(cdr, f);
+}

+ 27 - 0
08_SmartGroup/cdrapi.cpp

@@ -0,0 +1,27 @@
+#include <windows.h>
+#include "cdrapi.h"
+
+void BeginOpt(corel *cdr)
+{
+  auto name = _bstr_t("Undo");
+  cdr->EventsEnabled = false;
+  cdr->ActiveDocument->BeginCommandGroup(name);
+  cdr->ActiveDocument->Unit = cdrMillimeter;
+  cdr->Optimization = true;
+}
+
+void EndOpt(corel *cdr)
+{
+  cdr->EventsEnabled = true;
+  cdr->Optimization = false;
+  cdr->EventsEnabled = true;
+  cdr->ActiveDocument->ReferencePoint = cdrBottomLeft;
+  cdr->Application->Refresh();
+  cdr->ActiveDocument->EndCommandGroup();
+}
+
+void Active_CorelWindows(HWND hDlg)
+{                
+  // 将焦点返回到父窗口 关闭对话框窗口
+  SetFocus(GetParent(hDlg));
+}

+ 17 - 0
08_SmartGroup/cdrapi.h

@@ -0,0 +1,17 @@
+#ifndef CDRAPI_H_INCLUDED
+#define CDRAPI_H_INCLUDED
+
+#import "VGCoreAuto.tlb" \
+rename("GetCommandLine", "VGGetCommandLine") \
+rename("CopyFile", "VGCore") \
+rename("FindWindow", "VGFindWindow")
+
+#define corel VGCore::IVGApplication
+using namespace VGCore;
+
+
+void BeginOpt(corel *cdr);
+void EndOpt(corel *cdr);
+void Active_CorelWindows(HWND hDlg);
+
+#endif // CDRAPI_H_INCLUDED

+ 84 - 0
08_SmartGroup/cdrapp.cpp

@@ -0,0 +1,84 @@
+#include "cdrapp.h"
+
+// sr.ApplyUniformFill CreateCMYKColor(0, 100, 100, 0)
+bool fill_red(corel *cdr)
+{
+    auto sr = cdr->ActiveSelectionRange;
+    auto red = cdr->CreateCMYKColor(0, 100, 100, 0);
+    sr->ApplyUniformFill(red);
+
+    return true;
+}
+
+bool cql_OutlineColor(corel *cdr)
+{
+    auto col = cdr->CreateCMYKColor(0, 100, 100, 0);
+    auto s = cdr->ActiveShape;
+    col-> CopyAssign(s->Outline->Color);
+    col->ConvertToRGB();
+
+    auto r = col->RGBRed;
+    auto g = col->RGBGreen;
+    auto b = col->RGBBlue;
+
+    char buf[256] = { 0 };
+    sprintf(buf, "@Outline.Color.rgb[.r='%d' And .g='%d' And .b='%d']", r, g, b);
+    auto cql = _bstr_t(buf);
+    // MessageBox(NULL, cql, "cql 轮廓颜色", MB_ICONSTOP);
+    auto sr = cdr->ActivePage->Shapes->FindShapes(_bstr_t(), cdrNoShape, VARIANT_TRUE, cql);
+    sr->CreateSelection();
+    return true;
+}
+
+bool cql_FillColor(corel *cdr)
+{
+    auto col = cdr->CreateCMYKColor(0, 100, 100, 0);
+    auto s = cdr->ActiveShape;
+    col-> CopyAssign(s->Fill->UniformColor);
+    col->ConvertToRGB();
+
+    auto r = col->RGBRed;
+    auto g = col->RGBGreen;
+    auto b = col->RGBBlue;
+
+    char buf[256] = { 0 };
+    sprintf(buf, "@Fill.Color.rgb[.r='%d' And .g='%d' And .b='%d']", r, g, b);
+    auto cql = _bstr_t(buf);
+
+    auto sr = cdr->ActivePage->Shapes->FindShapes(_bstr_t(), cdrNoShape, VARIANT_TRUE, cql);
+    sr->CreateSelection();
+    return true;
+}
+
+bool cql_SameSize(corel *cdr)
+{
+    cdr->ActiveDocument->Unit = cdrMillimeter;
+    auto s = cdr->ActiveShape;
+
+    char buf[256] = { 0 };
+    sprintf(buf, "@width = {%lf mm} and @height = {%lf mm}", s->SizeWidth, s->SizeHeight);
+    auto cql = _bstr_t(buf);
+
+    //  MessageBox(NULL, cql, "cql 尺寸相同", MB_ICONSTOP);
+    auto sr = cdr->ActivePage->Shapes->FindShapes(_bstr_t(), cdrNoShape, VARIANT_TRUE, cql);
+    sr->CreateSelection();
+    return true;
+}
+
+bool Shapes_Filp(corel *cdr)
+{
+    BeginOpt(cdr);
+    auto sr = cdr->ActiveSelectionRange;
+    // CorelDRAW Shapes 物件 Item 编号从1开始
+    for (auto i = 0; i != sr->Count; i++)
+        sr->Shapes->Item[i + 1]->Flip(VGCore::cdrFlipHorizontal);
+
+    EndOpt(cdr);
+    return true;
+}
+
+bool  Clear_Fill(corel *cdr)
+{
+    cdr->ActiveSelection->Fill->ApplyNoFill();
+    return true;
+}

+ 19 - 0
08_SmartGroup/cdrapp.h

@@ -0,0 +1,19 @@
+#ifndef CDRAPP_H_INCLUDED
+#define CDRAPP_H_INCLUDED
+#include "cdrapi.h"
+
+bool fill_red(corel *cdr);
+bool cql_OutlineColor(corel *cdr);
+bool cql_FillColor(corel *cdr);
+bool cql_SameSize(corel *cdr);
+bool Shapes_Filp(corel *cdr);
+bool Shapes_Filp(corel *cdr);
+bool Clear_Fill(corel *cdr);
+
+void CdrCopy_to_AdobeAI(corel *cdr);
+void AdobeAI_Copy_ImportCdr(corel *cdr);
+
+bool Box_AutoGroup(corel *cdr);
+bool BBox_DrawRectangle(corel *cdr);
+
+#endif // CDRAPP_H_INCLUDED

BIN
08_SmartGroup/cpg.bmp


+ 58 - 0
08_SmartGroup/lycpg64.cbp

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+	<FileVersion major="1" minor="6" />
+	<Project>
+		<Option title="lycpg64" />
+		<Option pch_mode="2" />
+		<Option compiler="microsoft_visual_c_2022" />
+		<Build>
+			<Target title="Debug">
+				<Option output="bin/Debug/lycpg64" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Debug/" />
+				<Option type="3" />
+				<Option compiler="microsoft_visual_c_2022" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="/Zi" />
+					<Add option="/D_DEBUG" />
+				</Compiler>
+				<Linker>
+					<Add option="/debug" />
+				</Linker>
+			</Target>
+			<Target title="Release">
+				<Option output="bin/Release/lycpg64" prefix_auto="1" extension_auto="1" />
+				<Option object_output="obj/Release/" />
+				<Option type="3" />
+				<Option compiler="microsoft_visual_c_2022" />
+				<Option createDefFile="1" />
+				<Option createStaticLib="1" />
+				<Compiler>
+					<Add option="/Ox" />
+					<Add option="/DNDEBUG" />
+					<Add directory="../TypeLibs" />
+				</Compiler>
+			</Target>
+		</Build>
+		<Compiler>
+			<Add option="/W3" />
+			<Add option="/EHsc" />
+		</Compiler>
+		<Unit filename="ToolsBox.cpp" />
+		<Unit filename="ToolsBox.rc">
+			<Option compilerVar="WINDRES" />
+			<Option target="Release" />
+		</Unit>
+		<Unit filename="cdrPDF2Clip.cpp" />
+		<Unit filename="cdrapi.cpp" />
+		<Unit filename="cdrapi.h" />
+		<Unit filename="cdrapp.cpp" />
+		<Unit filename="cdrapp.h" />
+		<Unit filename="resource.h" />
+		<Unit filename="vbadll.cpp" />
+		<Extensions>
+			<lib_finder disable_auto="1" />
+		</Extensions>
+	</Project>
+</CodeBlocks_project_file>

+ 14 - 0
08_SmartGroup/resource.h

@@ -0,0 +1,14 @@
+#ifndef IDC_STATIC
+#define IDC_STATIC (-1)
+#endif
+
+#define IDD_TOOLS_BOX                           100
+#define IDB_BITMAP1                             101
+#define IDC_RED                                 40000
+#define IDC_CQL_FILL                            40001
+#define IDC_CQL_OUTLINE                         40002
+#define IDC_CQL_SIZE                            40003
+#define IDC_SR_FLIP                             40004
+#define IDC_CLEAR_FILL                          40005
+#define IDC_CDR2AI                              40006
+#define IDC_AI2CDR                              40007

+ 50 - 0
08_SmartGroup/vbadll.cpp

@@ -0,0 +1,50 @@
+
+#include "cdrapi.h"
+#include "cdrapp.h"
+
+extern corel *cdr;
+extern "C" __declspec(dllexport)
+int __stdcall vbadll(int code){
+
+try {
+    switch(code){
+        case 1:
+            AdobeAI_Copy_ImportCdr(cdr);
+        break;
+        
+        case 2:
+            CdrCopy_to_AdobeAI(cdr);
+        break;
+
+        case 3:
+            Clear_Fill(cdr);
+        break;
+
+        case 4:
+            Shapes_Filp(cdr);
+        break;
+
+        case 5:
+            cql_FillColor(cdr);
+        break;
+
+        case 6:
+            cql_OutlineColor(cdr);
+        break;
+
+        case 7:
+            cql_SameSize(cdr);
+        break;
+
+        case 8:
+            fill_red(cdr);
+        break;
+
+        default:
+            return 0;
+    }
+} catch (_com_error &e) {
+    MessageBox(NULL, e.Description(), "Error", MB_ICONSTOP);
+}
+    return code;
+}

+ 7 - 5
README.md

@@ -1,10 +1,12 @@
+### [捐赠 蘭雅 CorelDRAW CPG 开源项目](https://github.com/hongwenjun/corelvba/blob/main/donate.md)
+- [![](https://raw.githubusercontent.com/hongwenjun/vps_setup/master/img/youtube.png)频道](https://www.youtube.com/sRGB18/videos) &nbsp;&nbsp;www.youtube.com/sRGB18 &nbsp;&nbsp;[![](https://raw.githubusercontent.com/hongwenjun/vps_setup/master/img/paypal.png)赞赏支持!](https://paypal.me/sRGB18)&nbsp;&nbsp;https://paypal.me/sRGB18
+
 # CorelDRAW-CPG
 CorelDRAW CPG 扩展开发: CPG(Corel Plug-in Gallery)是 CorelDRAW 的一个扩展机制,可以开发自定义的插件和工具。
 
-
-
-
-
+## CorelDRAW-CPG C++ 编程傻瓜入门文档.xls [下载](./img/) 
+![](./img/cpgdoc_01.png) 
+![](./img/cpgdoc_02.png) 
 
 ## CorelDRAW Graphics Suite 2020  Programs64 TypeLibs
 
@@ -95,6 +97,6 @@ sr->CreateSelection();
 ### 使用 `Makefile` 用来编译,[参考视频](https://www.bilibili.com/video/BV1Nx4y1874F)
 ```shell
 nmake
-name install
+nmake install
 nmake clean
 ```

BIN
img/CorelDRAW-CPG C++ 编程傻瓜入门文档.xls


BIN
img/cpgdoc_01.png


BIN
img/cpgdoc_02.png