找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 3085|回复: 2

[分享] C#实现打开CAD文件时自动替换缺失字体

[复制链接]

已领礼包: 859个

财富等级: 财运亨通

发表于 2014-6-1 16:20:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
转自 http://hi.baidu.com/kakanimo/item/e36168dcd0cb764bddf9be5f

(原创)C#实现打开CAD文件时自动替换缺失字体


    经过N多天的研究,终于代码出来了;本着分享的精神,现在把代码都贴出来。ps:此程序算是本人的第一个完整的C#程序,必定存在拖沓冗余的代码。随着C#学习的深入,会不断优化。现在就将就看看过程思路吧。

    VB实现可以见http://hi.baidu.com/kakanimo/blog/item/4a69fe1e617a4f69f624e4ca.html,不过代码要自己修改下,VB中是进了CAD图再替换字体。完全根据我之前的那篇CAD替换字体框的研究写成打开图之前替换。

    此程序涉及的东西比较多。如调用API、CAD替换字体框的研究(http://hi.baidu.com/kakanimo/blog/item/83e1cffc04dc0049d7887d78.html)、CAD事件(看了几天C#的委托事件,也算看懂了,谁知CAD中事件太简单了,只需要连接下写下事件处理代码就可以了。囧,完全可以依样画瓢。)、多线程==,由于都是首次使用,基本上是依样画瓢。废话不说,上代码

using System;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;

namespace ChangeFonts
{
    class PublicTxtIndex
    {
        public static Thread TxtIndex;//声明一个静态变量

        public static Thread PublicTxtIndexN
        {
            get
            {
                return TxtIndex;
            }
            set
            {
                TxtIndex = value;
            }
        }

    }

    public class Init : IExtensionApplication
    {
        public void Initialize()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            ed.WriteMessage("MOKACAD插件初始化完成。");
            //启动事件
            ChangeFontEvent GoChange=new ChangeFontEvent();
            GoChange.addEvents();
        }
        public void Terminate()
        {
            //程序结束,在里做一些程序的清理工作
        }
    }
    public class ChangeFontEvent
    {
        DocumentCollection CreatNew = Application.DocumentManager;
        DLLChange.GOON dochange = new DLLChange.GOON();

        void documentCreateStarted(object sender, DocumentCollectionEventArgs e)
        {
            try
            {
                //如果这个时候还没有文档(原一个文档都没有,那到这里就要CAD致命错误)
                Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                ed.WriteMessage("开始自动替换字体");
            }
            catch
             {
             }

            Thread thread1 = new Thread(new ThreadStart(dochange.Reportfont));
            PublicTxtIndex.PublicTxtIndexN = thread1;
            StartOrAbort(true);
        }

       //打开或关闭
        void StartOrAbort(bool flag)
        {

            if (flag == true)//如果需要开启
            {
                PublicTxtIndex.PublicTxtIndexN.Start();
            }
            else
            {
                PublicTxtIndex.PublicTxtIndexN.Abort(); //终止线程

            }
        }

        void documentCreated(object sender, DocumentCollectionEventArgs e)
        {
                StartOrAbort(false);
                Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                ed.WriteMessage("自动替换字体结束");
        }

        [CommandMethod("AddEvents")]
        public void addEvents()
        {
            //把事件处理函数与相应的事件进行连接
            CreatNew.DocumentCreateStarted += new DocumentCollectionEventHandler(documentCreateStarted);
            CreatNew.DocumentCreated += new DocumentCollectionEventHandler(documentCreated);
        }

        [CommandMethod("RemoveEvents")]
        public void removeEvents()
        {
            //断开所有的事件处理函数
            CreatNew.DocumentCreateStarted -= new DocumentCollectionEventHandler(documentCreateStarted);
            CreatNew.DocumentCreated -= new DocumentCollectionEventHandler(documentCreated);
        }
    }
}

namespace DLLChange
{
    public delegate bool CallBack(int hwnd, int y);

    public class GOON
    {

        #region API声明
        [DllImport("user32.dll")]
        public static extern int EnumWindows(CallBack x, int y);

        [DllImport("user32.dll", EntryPoint = "EnumChildWindows")]//枚举子窗体
        public static extern bool EnumChildWindows(int hwndParent, CallBack EnumFunc, int lParam);

        [DllImport("User32.dll", EntryPoint = "FindWindow")]//找指定窗体
        private static extern int FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32")]
        public static extern int GetWindowText(int hwnd, StringBuilder lptrString, int nMaxCount);

        [DllImport("user32")]
        public static extern int IsWindowVisible(int hwnd);
        [DllImport("User32.Dll")]
        public static extern void GetClassName(int hwnd, StringBuilder s, int nMaxCount);


        [DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Ansi)]
        public static extern int SendMessage(int hwnd, int msg, int wParam, int lParam);

        [DllImport("User32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Ansi)]
        public static extern int SendMessage(int hWnd, int uMsg, int wParam, StringBuilder lParam);

        const int LB_SETTOPINDEX = 0x0197;
        const int LB_SETCURSEL = 0x0186;
        const int LB_GETCOUNT = 0x18B;

        const int WM_GETTEXT = 0x000D;
        const int BM_CLICK = 0x00F5;

        const int VK_UP = 0x26;//方向键
        const int VK_DOWN = 0x28;
        const int WM_CHAR = 0x102;
        const int WM_KEYDOWN = 0x100;
        #endregion

        #region 相当于public变量
        class ClassSqlString
        {
            public static int SqlString;//声明一个静态变量

            public static int GlobalUserName
            {
                get
                {
                    return SqlString;
                }
                set
                {
                    SqlString = value;
                }
            }

        }
        class PublicButtonHwnd
        {
            public static int ButtonHwnd;//声明一个静态变量

            public static int YButtonHwnd
            {
                get
                {
                    return ButtonHwnd;
                }
                set
                {
                    ButtonHwnd = value;
                }
            }

        }
        class PublicTxtIndex
        {
            public static int TxtIndex;//声明一个静态变量

            public static int PublicTxtIndexN
            {
                get
                {
                    return TxtIndex;
                }
                set
                {
                    TxtIndex = value;
                }
            }

        }
        #endregion

        #region 查找AutoCAD替换字体的窗口,返回得到这个窗口的句柄
        public bool Report(int hwnd, int lParam)
        {


            if (IsWindowVisible(hwnd) == 1)
            //if (pHwnd == 0 && IsWindowVisible(hwnd) == 1)
            {
                StringBuilder sb = new StringBuilder(512);

                GetWindowText(hwnd, sb, sb.Capacity);
                string CadString;
                CadString = sb.ToString();
                if (CadString.Length > 7 && CadString.Substring(0, 7) == "指定字体给样式")
                {//找到字体窗口
                    ClassSqlString.GlobalUserName = hwnd;
                    return false;
                }
            }
            return true;
        }
        #endregion

        #region 在这个替换字体的主窗口内查找子窗口
        public bool Reportfa(int hwnd, int lParam)//循环查找替换listbox
        {
            string lpszParentClass = "ListBox"; //整个窗口的类名
            StringBuilder sbClassName = new StringBuilder(255);
            GetClassName(hwnd, sbClassName, 255);
            //由于现查找到这个确定按钮,所以先设置这个值
            if (sbClassName.ToString() == "Button")
            {
                StringBuilder strButton = new StringBuilder(10);//用来存放窗口标题
                GetWindowText(hwnd, strButton, strButton.Capacity);
                if (strButton.ToString() == "确定")
                {
                    PublicButtonHwnd.YButtonHwnd = hwnd;//得到确定的按钮
                }
            }

            if (lpszParentClass == sbClassName.ToString())
            {
                //找到一个listbox,就看他的标题是不是空,空的舍弃
                StringBuilder str = new StringBuilder(512);//用来存放窗口标题
                GetWindowText(hwnd, str, str.Capacity);
                string strEnd = string.Empty;
                strEnd = str.ToString();//转换为字符串
                if (strEnd.Length > 0)//如果长度大于0,就找到这个啦
                {
                    if (PublicTxtIndex.PublicTxtIndexN == 0)
                    {
                        GetfontIndex(hwnd);
                    }
                    //设置listbox值
                    SendMessage(hwnd, LB_SETCURSEL, PublicTxtIndex.PublicTxtIndexN, 0);
                    //下移一行      
                    SendMessage(hwnd, WM_KEYDOWN, VK_DOWN, 0);
                    //发送确定按钮
                    SendMessage(PublicButtonHwnd.YButtonHwnd, BM_CLICK, 0, 0);

                    return false;
                }

            }
            return true;

        }
        #endregion

        #region 得到hztxt.shx的位置,设置PublicTxtIndexN
        public void GetfontIndex(int hwnd)
        {
            //先查找一共有多少项
            int ListCount;
            ListCount = SendMessage(hwnd, LB_GETCOUNT, 0, 0);
            StringBuilder strshx = new StringBuilder(20);//用来存放窗口标题
            for (int i = 0; i <= ListCount - 1; i++)
            {
                //设定某项来比较
                SendMessage(hwnd, LB_SETCURSEL, i, 0);
                //SendMessage(hwnd, LB_SETTOPINDEX, i, 0);//
                SendMessage(hwnd, WM_GETTEXT, strshx.Capacity, strshx);
                if (strshx.ToString() == "hztxt.shx|1|0000000")
                {
                    //得到hztxt前一个值
                    PublicTxtIndex.PublicTxtIndexN = i - 1;
                    break;
                }
            }
        }
        #endregion

        //循环查找替换
        public void Reportfont()
        {
           // Process[] ProcArray = Process.GetProcesses();
            int Nub = 1;
            while (Nub > 0)
            {
                EnumWindows(this.Report, 0);//这里会得到下面的kaka的值
                int kaka;
                kaka = ClassSqlString.GlobalUserName;//替换字体的对话框的句柄
                EnumChildWindows(kaka, this.Reportfa, 0);
                //this.DoEvents();
            }
        }

    }
}
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
发表于 2014-6-27 21:32:24 | 显示全部楼层
多谢分享,学习了
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

发表于 2014-6-29 20:19:21 | 显示全部楼层
多谢分享。。。。。。。。。。。。。。。。。。。。。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-12-19 02:03 , Processed in 0.397246 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表