<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          CAD嵌入Excel技術研究總結

          共 5829字,需瀏覽 12分鐘

           ·

          2020-08-01 15:15


          ?本篇技術關鍵詞:句柄、SetParent、VSTO

          最近一直在研究如何將CAD嵌入Excel中,并可以隨Excel主程序尺寸變化而自適應。本來要模仿E算量的效果。


          ab4886a3256d82d243fc7549c1f83c6c.webp



          82e5017114fd7c19c57e39e66ecf5cf5.webp




          無奈經(jīng)過窗口分析之后,E算量使用的是國外收費組件Xtreme ToolkitPro組件,VB.net又實在找不到合適的例子。雖然有類似的控件DockPanel,但是目前實在找不到外部窗體嵌入Excel主窗體中的例子(如果有好的例子,也希望大家推薦給我)。

          中間想過將CAD窗口放入Excel自定義任務窗格中,任務窗格不太靈活,寬度最多只能占據(jù)半個Excel操作區(qū)。






          最新的方案:將CAD窗口嵌入外部窗體,動態(tài)設置該窗體與Excel主窗體的位置關系。效果如下:








          碎碎念:

          發(fā)現(xiàn)最近比較鉆牛角尖,鉆進去很難出來,不達到自己滿意的效果,什么事情都不想做。這個玩意研究了一個多星期。這篇文章也只是記錄技術的實現(xiàn)過程,可能極少有人需要這玩意。

          最終極的解決方案,是利用鉤子技術,實時獲取Excel主程序的尺寸位置變化,來來動態(tài)調整CAD窗口的位置,作為野生程序員研究了幾天,委托,指針之類實在搞不明白,暫時擱置。





          ▌實現(xiàn)過程思路

          著重說原理和思路,代碼是次要的。本文所說效果是在vsto開發(fā)中實現(xiàn)的,使用的是VB.net語言。


          大致分為這幾個難點:


          • 使用SetParent函數(shù)將CAD窗口嵌入窗體, MoveWindow函數(shù)調整好CAD程序窗口和窗體的位置關系。
          • 獲取Excel主程序幾個常見區(qū)域的句柄。包括XLDESK、EXCEL7。為下一步將嵌入CAD程序的窗體放入Excel具體位置。





          ▌具體知識點
          • 句柄
          使用Windows API來操作窗口,都需要通過窗口的句柄來進行。所謂“句柄”,它是一個長整型的(Long:VB.NET中是Integer型)數(shù)據(jù),用來唯一地標識了一個存在的窗口,它是在窗口生成的同時由系統(tǒng)賦予于此窗口、并伴隨窗口“終身”,可以把它理解為窗口的“身份證號碼”。
          獲取一般窗體的句柄:Me.Handle獲取Excel主程序的句柄:Application.Hwnd獲取Excel窗口的子窗口XLDESK句柄:
           xldeskHwnd = FindWindowEx(xlhwnd, 0&, "XLDESK", vbNullString)
          其中xlhwnd為類名為XLMAIN的句柄(也就是Excel主程序的句柄Application.Hwnd)。

          api函數(shù)FindWindow可以根據(jù)指定的類名和窗口標題名稱獲得頂層窗口的句柄。

          FindWindowEx函數(shù)可以根據(jù)主窗口句柄,找到子窗口句柄。一般兩個API函數(shù)結合,獲取主窗口內部某個窗口的句柄。


          有了窗口句柄,可以做很多事情。

          bdaeaa83a8b93e6591306d9d8fe2ff74.webp








          • Excel窗口的結構:

          Excel主窗口(類名:XLMAIN)

              └────Excel工作區(qū)窗口(類名:XLDESK)

                    └────Excel工作簿窗口(Excel7)



          1c86e8236ead3b7f560b0254dfba9afb.webp





          • SetParent函數(shù)

          SetParent是一個API函數(shù),它的作用是為一個程序窗口指定一個新的父窗體。(父窗體嚴格來說是容器)。也就是把一個物體轉到另一個物體上去 ,Setparent 的用法相當簡單?。

          語法是:?
          Setparent? 物體句柄,目標句柄


          程序中,將CAD程序設置為窗體的子程序:

            SetParent(lHwnd, Me.Handle) 'lHwnd為CAD窗口的句柄,該句作用是設置本窗體為CAD的母窗體





          只要獲得窗口句柄,我們還可以將很多窗口嵌入Excel:


          34f87104260d1c911b817e506b8d3e26.webp




          • MoveWindow 函數(shù)


          ?函數(shù)功能:該函數(shù)改變指定窗口的位置和尺寸。對于頂層窗口,位置和尺寸是相對于屏幕的左上角的;對于子窗口,位置和尺寸是相對于父窗口客戶區(qū)的左上角坐標的。
           MoveWindow(ByVal hwnd As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal bRepaint As Integer) As Integer


          參數(shù):

            x:指定窗口的新位置的左邊界。

            Y:指定窗口的新位置的頂部邊界。

            nWidth:指定窗口的新的寬度。

            nHaight:指定窗口的新的高度。





          • GetWindowRect函數(shù):根據(jù)句柄,獲取對應窗體的坐標尺寸。



          這個函數(shù)是實現(xiàn)對齊窗體的核心!
           Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Integer, ByRef lpRect As RECT) As Integer Public Structure RECT        Dim Left As Integer        Dim Top As Integer        Dim Right As Integer        Dim Bottom As Integer End Structure





          ▌具體實現(xiàn)代碼
          • 在窗體加載的同時,獲取CAD程序,嵌入窗體中。并將窗體移動到Excel程序的合適位置。


                Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load        'SetHook()        xlhwnd = xlapp.Hwnd        xldeskHwnd = FindWindowEx(xlhwnd, 0&, "XLDESK", vbNullString)        GetWindowRect(xldeskHwnd, r)     '保存窗體原來的位置及大小到變量r        EXCEL7Hwnd = FindWindowEx(xldeskHwnd, 0&, "EXCEL7", vbNullString)        SetParent(Me.Handle, xldeskHwnd) '設置xldesk窗體為母窗體        '------------------------設置窗體按鈕panel位置---------------------------        '按鈕位置        Me.Panel1.Dock = DockStyle.Right        Me.Panel1.Left = Me.Left + Me.Width - 50        Me.Panel1.Width = 35        MoveWindow(Me.Handle, 0, 0, r.Width / 2, r.Height, True) '移動窗體位置        '--------------------------打開CAD--------------------------------------        Try            app = GetObject(, "AutoCAD.Application")            app.Visible = True        Catch ex As Exception            Try                app = CreateObject("AutoCAD.Application")            Catch dd As Exception                MsgBox("不能啟動AutoCAD,是否沒有安裝?")            End Try        End Try        '----------------------------------------------------------------        app.Visible = True '顯示cad程序界面        lHwnd = GetParent(GetParent(app.ActiveDocument.HWND)) '獲得CAD窗體的句柄        If lHwnd = 0 Then Exit Sub '如果沒有獲取大句柄,直接退出        '------------------------設置Excel7位置尺寸---------------------------        'Excel7位置尺寸        MoveWindow(EXCEL7Hwnd, r.Width / 2, 0, r.Width / 2, r.Height, True)        '----------------------------------------------------------------------------        SetParent(lHwnd, Me.Handle) '設置本窗體為CAD的母窗體        MoveWindow(lHwnd, 0, 0, Me.Width - 50, Me.Height, True)    End Sub






          • 人為拖動窗體尺寸變化,CAD自適應窗口Excel7工作區(qū)自適應變化。

          Private Sub Form2_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize        xlhwnd = xlapp.Hwnd        xldeskHwnd = FindWindowEx(xlhwnd, 0&, "XLDESK", vbNullString)        GetWindowRect(xldeskHwnd, r)     '保存窗體原來的位置及大小到變量r        EXCEL7Hwnd = FindWindowEx(xldeskHwnd, 0&, "EXCEL7", vbNullString)        MoveWindow(lHwnd, 0, 0, Me.Width - 50, Me.Height, True)        'Excel7位置尺寸        MoveWindow(EXCEL7Hwnd, Me.Width, 0, r.Width - Me.Width, r.Height, True)    End Sub




          • 關閉CAD,窗口恢復原樣

          Private Sub Form2_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing        'UnHook()        SetParent(lHwnd, 0)        app.WindowState = AutoCAD.AcWindowState.acNorm        '//EXCEL7窗口恢復        xlhwnd = xlapp.Hwnd        xldeskHwnd = FindWindowEx(xlhwnd, 0&, "XLDESK", vbNullString)        GetWindowRect(xldeskHwnd, r)     '保存窗體原來的位置及大小到變量r        EXCEL7Hwnd = FindWindowEx(xldeskHwnd, 0&, "EXCEL7", vbNullString)        MoveWindow(EXCEL7Hwnd, r.Left, 0, r.Width, r.Height, True)    End Sub




          • Excel主窗體尺寸變化時,各部分自適應尺寸變化。


          這部分完美的做法應該是利用HOOK技術,監(jiān)視Excel主程序窗口的變化。目前能力受限,由于目前是自用,也能滿足自身需求,優(yōu)化暫時擱置。

          Private Sub Application_WindowResize(Wb As Workbook, Wn As Window) Handles Application.WindowResize        xlhwnd = xlapp.Hwnd        xldeskHwnd = FindWindowEx(xlhwnd, 0&, "XLDESK", vbNullString) '獲取xldesk窗口句柄        EXCEL7Hwnd = FindWindowEx(xldeskHwnd, 0&, "EXCEL7", vbNullString) '獲取EXCEL7窗口句柄        formhandle = FindWindowEx(xldeskHwnd, 0&, vbNullString, "CAD窗口") '獲取標題名為CAD窗口的窗體句柄        If formhandle = 0 Then Exit Sub '獲取不到句柄,不做調整        GetWindowRect(xldeskHwnd, r)     '保存xldesk的位置及大小到變量r        MoveWindow(formhandle, 0, 0, r.Width / 2, r.Height, True) '實時移動窗體位置        GetWindowRect(formhandle, cadrect)     '保存修改過的cad窗體尺寸到=及位置到變量cadrect,為了下一步設置Excel7窗口的大小        MoveWindow(EXCEL7Hwnd, cadrect.Width, 0, r.Width - cadrect.Width, r.Height, True)    End Sub










          ▌寫在后面


          最初框架已經(jīng)形成,下一步就是慢慢填充各種算量小功能:






          有了上面的一些技術知識,可以初步做出來一個簡易聚光燈。


          思路是:疊加半透明異形窗體在Excel工作區(qū),利用SelectionChange事件動態(tài)調整窗口十字中心的位置。


          留待以后研究。







          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  东京热久久综合 | 麻豆国产一区二区 | 五月婷婷久久怎么了呀 | 日本黄色片视频 | 禁片天堂免费网址 |