2014-09-19 15 views
6

Używam stylów Delphi XE6 i VCL. Mam główną aplikację i biblioteki DLL. Moja główna aplikacja ma włączone tematy wykonawcze i używam plików w stylu vcl. Zrobiłem coś podobnego do moich bibliotek DLL. Włączyłem kompozycje uruchomieniowe i dodałem VCL.Themes, VCL.Style w ramach zastosowań i plik zasobów z plikiem w stylu VCL. Po załadowaniu biblioteki DLL ładuję styl VCL z zasobów i ustawię go dla biblioteki DLL. Główna aplikacja i biblioteka DLL nie są budowane z pakietami uruchomieniowymi.Styl VCL z biblioteki DLL wpływa na TMenuItem w aplikacji

Teraz mam GUI aplikacji głównej z własnym stylem i gui DLL w stylu z własnym stylem. To wydaje się działać dobrze, dopóki ...

Kiedy klikam przycisk w mojej głównej aplikacji, które wydarzenie otwiera TPopupMenu, jest stylizowany w tym samym stylu co GUI DLL zamiast głównego stylu aplikacji. Jeśli poruszam się po menu, dostaję AV i program się zawiesza. Spójrz na załączony obraz.

Co robię źle? Jedynym obejściem, jakie obecnie widzę, byłoby uczynienie mojego własnego dostosowanego TPopupMenu wyprowadzonego z innej kontroli. enter image description here


Jak obiecałem przygotowałem prosty program demo, który jest podobny do mojego wniosku. Składa się z aplikacji hosta o własnym stylu i DLL ze stylem dodanym do zasobu. Uruchom go i kliknij przycisk Popup następnie spróbuj wybrać coś z popup. Spowoduje to awarię i zatrzymanie się w niektórych StdWindowProc lub coś podobnego. Również jeśli przejdziesz do menu systemu okien (lewy górny róg), gdy spróbujesz wybrać coś z tego menu, zauważysz, że menu systemowe jest stylizowane jako GUI DLL i też się zawiesza. Link do pliku rar: dropbox.com/sh/f2jmbsmw18akpyg/AAA6SWdBmVhf6n6K-mvYLLmua?dl=0

enter image description here

Dzięki za pomoc.

+0

Najbardziej prawdopodobnym wyjaśnieniem jest przekazywanie obiektów VCL przez granicę między modułami, co jest niedozwolone, chyba że korzystasz z pakietów uruchomieniowych. –

+1

Druga możliwość, że mogę myśleć, że VCL kod style może flubs wyliczanie zasobów i wylicza zasobów w całym procesie. Szybkie skanowanie kodu sugeruje, że może to być problem, jeśli 'AutoDiscoverStyleResources' ma wartość' True'. To wołanie do 'EnumModules' wygląda dla mnie trochę niepewnie. –

+1

Jeśli nie można debugować to wtedy myślę prosicie nas kopać do niego. W tym celu może być potrzebny kod, który demonstruje problem. –

Odpowiedz

6

Jest to podstawowy problem ze stylami VCL i sposobem, w jaki obsługują one menu. Stylizacja jest realizowana za pomocą haka z procesami. W szczególności hak CBT instalowany przez wywołanie SetWindowsHookEx z TCustomStyleEngine.CreateSysHook w jednostce Vcl.Themes. W rzeczywistości hak ma zastosowanie tylko do wątku GUI, ale jest to proces szeroki w tym sensie, że w procesie jest dokładnie jeden wątek GUI.

Ponieważ w aplikacji jest wiele instancji VCL (jeden w bibliotece DLL i jeden w aplikacji), zainstalowane są dwa zaczepy. To o jeden za dużo. Zainstalowany ostatnio hak (biblioteka DLL) wygrywa, dlatego styl menu DLL infekuje twój plik wykonywalny. I dlaczego masz do czynienia z naruszeniem dostępu. Biblioteka DLL próbuje działać w menu należącym do pliku wykonywalnego. Mimo to, pomimo wszelkich starań, zakończyłeś korzystanie z kodu VCL obiektów DLL z pliku wykonywalnego hosta.

Nie ma prostego sposobu obejścia tego i wspierania stylów w pełni w obu modułach. To, co tu mamy, jest fundamentalną konsekwencją projektu. System nie został zaprojektowany do obsługi wielu instancji VCL. Jeśli chcesz używać stylów VCL w wielu modułach, projektanci oczekują, że użyjesz pakietów runtime.

Przypuszczam, że możesz uzyskać trochę przyczepności, operując biblioteką DLL z zupełnie innego wątku. Wymagałoby to załadowania biblioteki DLL z tego innego wątku, aby VCL został zainicjowany w wątku. Wszystkie wywołania do biblioteki DLL muszą pochodzić z tego wątku. I musisz uruchomić pętlę wiadomości w tym wątku. Możliwe, że będziesz w stanie wykonać tę pracę, ale wątpię w to. Mimo wszystkich wspomnianych warunków nadal musisz sobie poradzić z tym, że masz dwa wątki GUI, które przedstawiają różnego rodzaju problemy z obsługą kolejki wejściowej.

Może innym podejściem byłoby odinstalować haczyk z DLL. Dopóki twoja biblioteka DLL nie wyświetla menu, możesz odłączyć się od odinstalowania tego haka. Wyłączałoby to stylizację menu wyświetlaną przez bibliotekę DLL, ale być może jest to do zaakceptowania.

Ta wersja biblioteki DLL (po I uproszczone go nieco również) odinstalowuje haka.

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. 

Ta wersja biblioteki DLL sprawia, że ​​plik wykonywalny komputera nie powoduje problemów opisanych w pytaniu.

+0

Dziękuję David za wyjaśnienie. Od tego czasu używaliśmy zewnętrznych kontrolerów AlphaControls, aby skroić naszą aplikację, ale teraz zdecydowaliśmy się używać stylów Delphi VCL i właśnie odkrywam technologię, która za tym stoi. Dziękuję również za edytowanie/sprawdzanie mojego postu i sprawienie, że ten temat będzie bardziej czytelny. Bardzo to doceniam. – Nix

+0

Nie ma za co. Dziękujemy za wspaniałą pracę polegającą na przekazywaniu informacji i współpracy z nami, aby zadać dobre pytanie i rozwiązać problem. Przy okazji powinieneś, gdy będziesz gotowy, zaakceptować odpowiedź, którą uznasz za najlepszą. Twój wybór. –

+0

+1 doskonałe wyjaśnienie :) –

7

jak David mówi, że to jest spowodowane, ponieważ każda instancja VCL zainstalować hak do wykrycia, gdy menu podręczne (# 32768) jest tworzony. Tak więc działają dwie instancje haczykowe w tym samym czasie.

W celu obejścia problemu można wyłączyć przechwycenie stylu menu podręcznego w dll (lub w aplikacji) za pomocą funkcji UnRegisterSysStyleHook zdefiniowanej w jednostce Vcl.SysStyles.

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

+1 za pokazanie oficjalną drogę do wyrejestrowania ten hak –

+0

I nie wiedziała o tym, ale dlatego, że właśnie rozpoczęła style VCL i nie jestem zaznajomiony z nimi jeszcze. Odtąd używaliśmy zewnętrznych kontrolek Alpha, ale zdecydowaliśmy się na delphi VCL style. Dziękuję Ci. – Nix

Powiązane problemy