VerySource

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 330|回复: 0

Ribbon Images in Excel 2007/2010 using a Delphi COM DLL

[复制链接]

1

主题

2

帖子

2.00

积分

新手上路

Rank: 1

积分
2.00
发表于 2023-10-1 22:22:41 | 显示全部楼层 |阅读模式
1金币
Vấn đề này đã tồn tại hơn một năm. Thỉnh thoảng tôi nhặt nó lên và thử một số cách khắc phục, thấy chúng không hoạt động và lại đặt nó xuống. Tuy nhiên đêm qua tôi đã tìm ra giải pháp cho toàn bộ vấn đề và Tôi muốn viết nó ra để những người khác có thể hưởng lợi từ kiến ​​thức này.
Nếu bạn xem lại hầu hết kiến ​​thức về các điều khiển Office Ribbon, các ví dụ luôn có trong Visual Studio, nơi một số thao tác được thực hiện ở chế độ nền cho bạn. Với Delphi, bạn cần hiểu tất cả những chi tiết thực tế để giải pháp hoạt động.
Những gì tôi sắp làm là mô tả từng phần giải pháp và chỉ ra những vấn đề tôi phải vượt qua và tại sao chúng lại là vấn đề.
Đầu tiên là kích hoạt Ribbon tùy chỉnh của bạn để yêu cầu hình ảnh. Việc này được thực hiện theo hai phần. Đầu tiên, bằng cách thêm thẻ LoadImage vào thành phần customUI như sau:   
<customUI xmlns = "http://schemas.microsoft.com/office/2006/01/customui" onLoad = " RibbonLoaded " LoadImage = "GetImage" >
Trong đó GetImage là tên của hàm gọi lại trong COM DLL của tôi.  
Thứ hai, chúng tôi thêm thẻ hình ảnh vào các thành phần nút của dải băng tùy chỉnh như sau:  
<button id = "EidolonAbout" label = "Giới thiệu" onAction = " RibbonClick " image = "EidolonAbout" keytip = "A" screentip = "Hiển thị đoạn hội thoại Giới thiệu" supertip = "Tùy chọn này hiển thị đoạn hội thoại giới thiệu để bạn có thể lấy thông tin của Eidolon số phiên bản để được hỗ trợ." />
Trong đó “EidolonAbout” là tên sẽ được truyền cho hàm GetImage() .   
Trước khi chúng ta bắt đầu triển khai GetImage() trong COM DLL, hãy đảm bảo rằng chúng ta có một số hình ảnh để làm việc. Tôi thích tạo các hình ảnh bên ngoài bằng bất kỳ gói nào ( GIMP hoặc Borland Image Editor) và đặt chúng vào một cửa sổ tệp tài nguyên bằng cách sử dụng tập lệnh tài nguyên. Dưới đây là một phần của tập lệnh RC cho những hình ảnh này:   
...           ICON EidolonNewQueryImage "Hình ảnh\Hình ảnh thanh công cụ\EidolonNewQueryImage.ico"      ICON EidolonNewPivotTableImage "Hình ảnh\Hình ảnh thanh công cụ\EidolonNewPivotTableImage.ico" EidolonEditQueryPivotImage     ICON "Hình ảnh\Hình ảnh thanh công cụ\EidolonEditQueryPivotImage.ico" EidolonUpdateQueryPivot   Hình ảnh ICON "Hình ảnh\Hình ảnh thanh công cụ\EidolonUpdateQueryPivotImage. ico " ...
Nếu bạn liên kết điều này với dự án của mình thì nó sẽ được kiểm tra và biên dịch cùng với dự án của bạn. Điều này sau đó cho phép chúng tôi tải hình ảnh từ DLL và không phải duy trì các tệp bên ngoài bổ sung.
Bạn sẽ nhận thấy rằng tôi đã sử dụng các tệp biểu tượng cho hình ảnh thay vì bitmap. Khi tôi thử bitmap, chúng không hoạt động giống như trong Delphi với pixel dưới cùng bên trái được sử dụng làm màu trong suốt. Có lẽ tôi đang nghĩ gì đó thiếu ở đây Ngoài ra, tôi đã thêm tên “Hình ảnh” vào cuối tất cả các tệp biểu tượng vì tôi có rất nhiều hình ảnh trong DLL cho các thành phần khác nhau và vì vậy muốn đảm bảo không có xung đột tên.
Vì vậy, bây giờ chúng ta đến phần khó khăn nhất, việc triển khai GetImage() .
Đầu tiên chúng ta cần thêm một phương thức vào lớp tự động hóa của COM DLL như sau:
  IEidolonAddin = giao diện ( IDispatch ) [ '{25F65BDF-36E0-4A51-B222-8A86AC4CCCCB}' ] Thủ tục RibbonClick ( Const control : IRibbonControl ) ; safecall ; Thủ tục RibbonLoaded ( Const RibbonUI : IRibbonUI ) ; safecall ; hàm GetImage ( Const imageName : WideString ) : IPictureDisp ; safecall ; kết thúc ;                     IEidolonAddinDisp = dispinterface [ '{25F65BDF-36E0-4A51-B222-8A86AC4CCCCB}' ] Thủ tục RibbonClick ( Kiểm soát const : IRibbonControl ) ; DispID 201 ; Thủ tục RibbonLoaded ( Const RibbonUI : IRibbonUI ) ; DispID 202 ; hàm GetImage ( Const imageName : WideString ) : IPictureDisp ; DispID 203 ; kết thúc ;                   
Bây giờ tôi luôn nghĩ rằng thông tin này đã được đồng bộ hóa với tệp RIDL nhưng đối với tôi thì không, chúng ta sẽ đến với tệp RIDL ở cuối.
Rõ ràng điều này có nghĩa là phương thức cần được triển khai trong lớp tự động hóa như sau:
    TEidolonAddin = Lớp ( TAutoObject , IUnknown , IDispatch , IEidolonAddin , IDTExtensibility2 , IRibbonExtensibility ) ... Public ... Chức năng GetImage ( Const imageName : WideString ) : IPictureDisp ; Safecall ; End ;                                     Hàm TEidolonAddin .GetImage ( Const imageName : WideString ) : IPictureDisp ; _   Var PictureDesc : TPictDesc ;      Bắt đầu Kết quả : = Nil ; PictureDesc . cbSizeofstruct : = SizeOf ( PictureDesc ) ; PictureDesc . picType : = PICTYPE_ICON ; PictureDesc . hIcon : = LoadIcon ( HInstance , PWideChar ( imageName + 'Image' ) ) ; Nếu PictureDesc . hIcon <> 0 Thì Case OleTạoHình ảnhGián tiếp                           ( PictureDesc , ActiveX . IPicture , True , Result ) Của E_NOINTERFACE : OutputDebugString ( 'Picture NO INTERFACE' ) ; E_POINTER : OutputDebugString ( 'Picture NO POINTER' ) ; S_OK : OutputDebugString ( 'Picture OK' ) ; Ngược lại OutputDebugString ( 'Picture Unknown' ) ' ) ; Kết thúc ; Kết thúc ;                                                               
Phương pháp này đơn giản một cách đáng ngạc nhiên. Nó lấy các hình ảnh biểu tượng từ tài nguyên DLL và chuyển nó tới phương thức OLECreatePictureIndirect để tạo hình ảnh được chuyển sang Excel. Bạn sẽ nhận thấy rằng có một số mã gỡ lỗi ở đây. Tôi cần phải thực hiện từng bước một mã này để hiểu liệu lý do hình ảnh không xuất hiện trong Excel có phải là do nó không được tạo đúng cách trong Delphi hay không.  
Như đã xảy ra, mã này không phải là vấn đề thực sự. Phương thức này được gọi và chạy bình thường nhưng ngay sau khi quá trình thực thi diễn ra ngoài hàm, Excel bị khóa hoặc bị khóa tùy thuộc vào việc đó là Excel 2007 hay 2010. Điều này khiến tôi nghĩ về định nghĩa về thành phần thư viện kiểu được liên kết với lệnh gọi này.
Tôi đã nhầm tưởng rằng bạn chỉ có sẵn các mục trong danh sách thả xuống nên định nghĩa của tôi như sau:
IPicture * _stdcall GetImage ([ in ] BSTR imageName );
Tôi đã tìm trên mạng để xem có ai đã đăng giải pháp cho vấn đề này không và tìm thấy một trang web tiếng Nga (Delphi Masters) có giải pháp đó.Thật không may, tiếng Nga của tôi không tồn tại NHƯNG bằng cách xem xét mã một cách có phương pháp, tôi đã tìm thấy có lẽ.Đó là bởi vì định nghĩa RIDL ở trên là sai và lẽ ra nó phải như dưới đây.
HRESULT _stdcall GetImage ([ in ] BSTR imageName , [ out , retval ] IPictureDisp ** aImage );
Tôi chạy mã (vào thời điểm đó tôi rất hy vọng rằng nó sẽ hoạt động) và tôi đã thử nhấp vào Excel sau khi duyệt qua mã để xem liệu nó có phản hồi hay không và tôi ngạc nhiên là có một hình ảnh nhỏ bên cạnh một trong các nút của tôi

回复

使用道具 举报

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

本版积分规则

Archiver|手机版|CopyRight © 2008-2023|verysource.com ( 京ICP备17048824号-1 )

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