2014-09-19 16 views
6

Tôi đang sử dụng kiểu Delphi XE6 và VCL. Tôi có ứng dụng và dll chính. Ứng dụng chính của tôi đã bật các chủ đề thời gian chạy và tôi đang sử dụng các tệp kiểu vcl. Tôi đã làm điều tương tự như DLL của tôi. Tôi đã bật các chủ đề thời gian chạy và thêm VCL.Themes, VCL.Styles theo sử dụng và tệp tài nguyên với tệp kiểu VCL bên trong nó. Khi DLL được nạp, tôi tải kiểu VCL từ tài nguyên và thiết lập nó cho DLL gui. Ứng dụng chính và DLL không được xây dựng với các gói thời gian chạy.Kiểu VCL từ DLL đang ảnh hưởng đến TMenuItem trong Ứng dụng

Bây giờ tôi có giao diện đồ họa ứng dụng chính với phong cách riêng và kiểu gui dll theo phong cách riêng. Điều này dường như hoạt động tốt cho đến khi ...

Khi tôi nhấp vào nút trong ứng dụng chính của mình, sự kiện sẽ mở TPopupMenu, nó được tạo kiểu với cùng một kiểu như GUI DLL thay vì kiểu ứng dụng chính. Nếu tôi điều hướng thông qua menu tôi nhận được AV và chương trình bị treo. Hãy xem hình ảnh đính kèm.

Tôi đang làm gì sai? Cách giải quyết duy nhất mà tôi đang thấy sẽ là tạo ra TPopupMenu tùy chỉnh của riêng tôi từ một số điều khiển khác. enter image description here


Như tôi đã hứa, tôi đã chuẩn bị chương trình demo đơn giản tương tự ứng dụng của tôi. Nó bao gồm các ứng dụng máy chủ với phong cách riêng và DLL với phong cách thêm vào tài nguyên. Chạy nó và bấm vào nút Popup sau đó thử chọn một cái gì đó từ popup. Nó sẽ sụp đổ và dừng lại ở một số StdWindowProc hoặc một cái gì đó như thế. Ngoài ra nếu bạn vào menu hệ thống cửa sổ (góc trên cùng bên trái) khi bạn cố gắng chọn một cái gì đó từ trình đơn đó, bạn sẽ thấy rằng menu hệ thống được tạo kiểu như dll gui và treo quá. Liên kết đến tập tin rar: dropbox.com/sh/f2jmbsmw18akpyg/AAA6SWdBmVhf6n6K-mvYLLmua?dl=0

enter image description here

Nhờ sự giúp đỡ của bạn.

+0

Giải thích rất có thể là bạn đang truyền các đối tượng VCL qua ranh giới giữa các mô-đun của bạn, điều này không được phép trừ khi bạn sử dụng các gói thời gian chạy. –

+1

Một khả năng khác mà tôi có thể nghĩ đến là mã kiểu VCL có lẽ sẽ xóa liệt kê tài nguyên và liệt kê các tài nguyên trong toàn bộ quá trình. Việc quét nhanh mã cho thấy có thể là một vấn đề nếu 'AutoDiscoverStyleResources' là' True'. Cuộc gọi đó đến 'EnumModules' trông hơi khó chịu với tôi. –

+1

Nếu bạn không thể gỡ lỗi này thì tôi đoán bạn đang yêu cầu chúng tôi đào sâu vào nó. Để làm như vậy, chúng tôi có thể cần phải có mã chứng minh sự cố. –

Trả lời

6

Đây là vấn đề cơ bản với phong cách VCL và cách chúng tạo kiểu menu. Kiểu dáng được thực hiện với một móc quá trình rộng. Cụ thể là móc nối CBT được cài đặt bằng một cuộc gọi đến SetWindowsHookEx từ TCustomStyleEngine.CreateSysHook trong đơn vị Vcl.Themes. Trong thực tế, hook chỉ áp dụng cho thread GUI, nhưng đó là quá trình rộng theo nghĩa là có chính xác một luồng GUI trong tiến trình.

Vì bạn có nhiều phiên bản của VCL trong ứng dụng của bạn (một trong DLL và một trong ứng dụng), hai móc được cài đặt. Đó là một quá nhiều. Móc được cài đặt gần đây nhất (DLL khi nó xảy ra) thắng, và đó là lý do kiểu dáng trình đơn DLL lây nhiễm vào tệp thực thi của bạn. Và tại sao bạn gặp phải vi phạm truy cập. DLL đang cố gắng hoạt động trên một menu thuộc về tệp thực thi. Và như vậy, mặc dù những nỗ lực tốt nhất của bạn, bạn đã kết thúc với mã DLL truy cập các đối tượng VCL từ máy chủ thực thi.

Không có cách nào đơn giản để giải quyết vấn đề này và hỗ trợ đầy đủ các kiểu trong cả hai mô-đun. Những gì chúng ta có ở đây là một hệ quả cơ bản của thiết kế. Hệ thống không được thiết kế để hỗ trợ nhiều phiên bản VCL. Nếu bạn muốn sử dụng các kiểu VCL trong nhiều mô-đun, thì các nhà thiết kế mong bạn sử dụng các gói thời gian chạy.

Tôi cho rằng bạn có thể có được lực kéo bằng cách vận hành DLL ra khỏi một chuỗi hoàn toàn khác. Điều đó sẽ liên quan đến việc tải các DLL từ đó thread khác nhau để VCL được khởi tạo trong thread. Và tất cả các cuộc gọi đến DLL sẽ phải từ chuỗi đó. Và bạn cần chạy một vòng lặp tin nhắn trong chuỗi đó. Có thể bạn có thể làm được công việc đó, nhưng tôi nghi ngờ điều đó. Ngay cả với tất cả các provisos đề cập đến bạn vẫn phải xử lý thực tế là bạn có hai GUI chủ đề mà trình bày tất cả các loại vấn đề với xử lý hàng đợi đầu vào.

Có lẽ một cách tiếp cận khác là gỡ cài đặt móc từ DLL. Vì vậy, miễn là DLL của bạn không hiển thị menu thì bạn cũng có thể thoát khỏi việc gỡ cài đặt hook đó. Nó sẽ vô hiệu hóa phong cách cho các menu được hiển thị bởi các DLL, nhưng có lẽ đó là chấp nhận được.

Phiên bản này của DLL của bạn (sau khi tôi đơn giản hóa nó phần nào cũng) gỡ cài đặt móc.

library VCLStyleDLL; 

{$R 'Style.res' 'Style.rc'} 

uses 
    VCL.Styles, 
    VCL.Themes, 
    VCL.SysStyles; // to gain access to TSysPopupStyleHook 

{$R *.res} 

begin 
    TStyleManager.TrySetStyle('Glossy', false); 
    TCustomStyleEngine.UnRegisterSysStyleHook('#32768', TSysPopupStyleHook); 
end. 

Với phiên bản này của DLL, máy chủ thực thi không gặp vấn đề mô tả trong câu hỏi của bạn.

+0

Cảm ơn bạn David đã giải thích. Kể từ bây giờ, chúng tôi đã sử dụng AlphaControls của bên thứ ba cho ứng dụng của chúng tôi nhưng bây giờ chúng tôi quyết định sử dụng phong cách VCL Delphi và tôi chỉ khám phá ra công nghệ đằng sau nó. Cảm ơn bạn cũng đã chỉnh sửa/đánh giá bài đăng của tôi và làm cho chủ đề này dễ đọc hơn. Tôi rất trân trọng điều này. – Nix

+0

Bạn được hoan nghênh. Cảm ơn bạn đã làm tốt công việc cung cấp thông tin và làm việc với chúng tôi để tạo ra một câu hỏi hay và giải quyết vấn đề của bạn. Btw, bạn nên, khi bạn đã sẵn sàng, chấp nhận câu trả lời bạn cho là tốt nhất. Lựa chọn của bạn. –

+0

+1 giải thích tuyệt vời :) –

7

Như David nói điều này là do mỗi cá thể VCL cài đặt móc để phát hiện khi menu bật lên (# 32768) được tạo. Vì vậy, có hai trường hợp móc làm việc cùng một lúc.

Như cách giải quyết khác, bạn có thể tắt móc kiểu popupmenu trong dll (hoặc trong ứng dụng) bằng hàm UnRegisterSysStyleHook được xác định trong đơn vị Vcl.SysStyles.

TCustomStyleEngine.UnRegisterSysStyleHook('#32768', TSysPopupStyleHook); 
+0

+1 để hiển thị cách chính thức để hủy đăng ký móc này –

+0

Tôi đã không nhận thức được điều đó nhưng vì tôi mới bắt đầu với phong cách VCL và tôi chưa quen với chúng. Kể từ bây giờ chúng tôi sử dụng các điều khiển Alpha của bên thứ ba nhưng chúng tôi quyết định đi với các phong cách VCL delphi. Cảm ơn bạn. – Nix

Các vấn đề liên quan