CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Listowanie dostępnych wartości dla dowolnego enumeratora

Listowanie dostępnych wartości dla dowolnego enumeratora

dział ogólny

Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Mironas » piątek, 9 sierpnia 2013, 18:45

Potrzebuję wylistować wartości dostępne dla dowolnego enumeratora (TAlign/TWindowState/TFormStyle/...) przy założeniu, że posiadam nazwę typu w stringu - np:
KOD cpp:     UKRYJ  
String enumtype = "TAlign";


Napisałem funkcję która (prawie) to robi ale nie potrafię zamienić stringa z nazwą typu na TMetaClass lub od razu na TTypeInfo.
Wygląda to tak:
KOD cpp:     UKRYJ  
void __fastcall TForm1::Button11Click(TObject *Sender)
{
  String enumtype = "TAlign";
  GetEnumNames(enumtype, Memo1->Lines);
}
//---------------------------------------------------------------------------
void TForm1::GetEnumNames(String enumtype, TStrings* enumnames)
{
  // Wypelnia liste 'enumnames' nazwami wartosci enumeratora
  // -------------------------------------------------------
  TMetaClass* MC = ????(enumtype);                // TUTAJ zamienić "TAlign" na TMetaClass
  TTypeInfo* TI = (TTypeInfo*)MC->ClassInfo();    // ALBO TUTAJ zamienić "TAlign" na TTypeInfo
  TTypeData* TD = GetTypeData(TI);
  String nazwa;

  enumnames->Clear();
  if ( TI->Kind == tkEnumeration )
  {
    for (int i=TD->MinValue ; i<=TD->MaxValue ; i++)
    {
      nazwa = GetEnumName(TI, i);
      enumnames->Add(nazwa);
    }
  }
}
//---------------------------------------------------------------------------
 

A może ktoś ma zupełnie inny pomysł?
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Cyfrowy Baron » piątek, 9 sierpnia 2013, 19:01

To niemożliwe! Program musi wiedzieć co tworzy, a nie przekonwertujesz wartości typu String na klasę. Zastanawiam się nad życiem funkcji ogólnej, ale nawet w takim przypadku musiałbyś zadeklarować w programie wszystkie typy jakich chcesz użyć.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Mironas » piątek, 9 sierpnia 2013, 19:35

Cyfrowy Baron napisał(a):Program musi wiedzieć co tworzy

Pisząc "dowolny enumerator" oczywiście miałem na myśli tylko te które są zdefiniowane w zainkludowanych plikach nagłówkowych.

Cyfrowy Baron napisał(a):nie przekonwertujesz wartości typu String na klasę

A jakiś inny sposób na wylistowanie wartości?

Np mogę to zrobić jeśli dysponuję komponentem posiadającym taką właściwość i znam jej nazwę:
KOD cpp:     UKRYJ  
  String propname = "Align";
  TPropInfo* PI = GetPropInfo(Button1, propname);
  TTypeInfo* TI = *(PI->PropType);
  TTypeData* TD = GetTypeData(TI);
  String proptype = AnsiString((*PI->PropType)->Name);
  String enumname;

  if ( TI->Kind == tkEnumeration )
  {
    Memo1->Clear();
    for (int i=TD->MinValue ; i<=TD->MaxValue ; i++)
    {
      enumname = GetEnumName(TI, i);
      Memo1->Lines->Add(enumname);
    }
  }
 

Teoretycznie mogę obciąć T w TAlign i zastosować powyższy kod. Tylko musiałbym za każdym razem wyszukać komponent posiadający taką właściwość. Ale to bardzo nieeleganckie rozwiązanie. Wolałbym coś prostszego.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Cyfrowy Baron » sobota, 10 sierpnia 2013, 09:44

Zawsze musisz podać nazwę obiektu, którego właściwości chcesz odczytać. Przecież program musi się odwoływać do konkretnego adresu w pamięci. Jak chciałbyś pobrać uchwyt do hipotetycznego obiektu? Posłuż się funkcją FindComponent. Może coś w tym rodzaju:

KOD cpp:     UKRYJ  
TPropInfo* PI = GetPropInfo( reinterpret_cast<TWinControl *>( FindComponent( "NazwaObiektu") ), propname );


Wykorzystałem rzutowanie polimorficzne na klasę TWinControl, gdyż wiele obiektów dziedziczy po niej właściwości w tym np. TAlign.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Mironas » poniedziałek, 12 sierpnia 2013, 10:18

Komponent to nie problem. Mogę sobie nawet tworzyć go dynamicznie tylko po to aby odczytać dostępne wartości jakiegoś parametru. Jednak to i tak nie załatwia mi głównego problemu, czyli zamiany nazwy klasy numeratora (w stringu) na listę dostępnych wartości.
No ale jak się nie da to się nie da. Dzięki za zainteresowanie.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Cyfrowy Baron » poniedziałek, 12 sierpnia 2013, 11:19

Mironas napisał(a):czyli zamiany nazwy klasy numeratora (w stringu) na listę dostępnych wartości.


To zdanie jest dla mnie kompletnie niezrozumiałe...
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Mironas » poniedziałek, 12 sierpnia 2013, 11:31

Cyfrowy Baron napisał(a):
Mironas napisał(a):czyli zamiany nazwy klasy numeratora (w stringu) na listę dostępnych wartości.


To zdanie jest dla mnie kompletnie niezrozumiałe...


Powinno być:
"Pozyskanie dostępnych wartości enumeratora na podstawie nazwy klasy" (trudno to czytelnie określić).

Np.:
"TAlign" >> "alNone", "alTop", "alBottom", "alLeft", "alRight", "alClient", "alCustom"
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Cyfrowy Baron » poniedziałek, 12 sierpnia 2013, 12:39

Bo tak piszesz... Dla przykładu TAlign to nie jest klasa lecz typ wyliczeniowy. Poza tym typy wyliczeniowe mają po prostu kolejne numery indeksu licząc od 0. Chyba myli ci się typ wyliczeniowy np. z dyrektywą #define?

Wartość typu wyliczeniowego łatwo sprawdzić, np:

KOD text:     UKRYJ  
enum TAlign : unsigned char { alNone, alTop, alBottom, alLeft, alRight, alClient, alCustom };


czyli np. alRight ma wartość 4 - sprawdzamy:

KOD cpp:     UKRYJ  
Caption = (int)alRight;


A poza tym mając nazwę naprawdę nie trudno za pomocą twojego kodu pobrać wartość:

KOD cpp:     UKRYJ  
  String propname = "Align";
  TPropInfo* PI = GetPropInfo(Button1, propname);
  TTypeInfo* TI = *(PI->PropType);
  TTypeData* TD = GetTypeData(TI);
  String proptype = AnsiString((*PI->PropType)->Name);
  String enumname;

  if ( TI->Kind == tkEnumeration )
  {
    Memo1->Clear();
        for (int i=TD->MinValue ; i<=TD->MaxValue ; i++)
    {
          enumname = GetEnumName(TI, i);
      Memo1->Lines->Add( enumname + " " + (String)GetEnumValue(TI, enumname) );
    }
  }
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Mironas » poniedziałek, 12 sierpnia 2013, 13:08

Cyfrowy Baron napisał(a):Chyba myli ci się typ wyliczeniowy np. z dyrektywą #define?

Nie, nie myli mi się. Chodzi o typ wyliczeniowy ENUM (który tutaj nazywałem enumeratorem).

Cyfrowy Baron napisał(a):Wartość typu wyliczeniowego łatwo sprawdzić

Ale mi nie chodzi o podejrzenie pliku nagłówkowego tylko o wylistowanie tych wartości w programie (np wpisanie ich w Memo).

Cyfrowy Baron napisał(a):A poza tym mając nazwę naprawdę nie trudno za pomocą twojego kodu pobrać wartość:

Tak - mając nazwę właściwości komponentu Align (razem z komponentem posiadającym tą właściwość) można łatwo pobrać te wartości. Ale mi chodziło o pobranie wartości wtedy gdy mam tylko nazwę typu TAlign (lub dowolnego innego zainkludowanego typu wyliczeniowego).

No ale jeśli się nie da to trudno.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Cyfrowy Baron » poniedziałek, 12 sierpnia 2013, 14:00

Mironas napisał(a):Tak - mając nazwę właściwości komponentu Align (razem z komponentem posiadającym tą właściwość) można łatwo pobrać te wartości. Ale mi chodziło o pobranie wartości wtedy gdy mam tylko nazwę typu TAlign (lub dowolnego innego zainkludowanego typu wyliczeniowego).


A z czego chciałbyś to pobrać? Przecież jeżeli chcesz pobrać te dane z aplikacji to taki obiekt klasy musi istnieć w tej aplikacji. Klasa to tylko projekt obiektu nie obiekt nie jest dołączana do aplikacji jeżeli obiekt tworzony w oparciu o tą klasę nie jest zadeklarowany w aplikacji. Typ wyliczeniowy nie istnieje w jakiejś abstrakcyjnej przestrzeni, musi być przypisany do czegoś i właśnie z tego czegoś trzeba go pobierać.

Mironas napisał(a):lub dowolnego innego zainkludowanego typu wyliczeniowego


Przecież nie istnieje żadna biblioteka, która by zawierała spis typów wyliczeniowych. Nawet jeżeli właczysz do projektu bibliotekę zawierającą klasy obiektów korzystających a jakiegoś typu wyliczeniowego, to mamy do czynienia z sytuacją, którą opisałem wyżej - musi zostać zadeklarowany obiekt w oparciu o tą klasę inaczej to tak jakbyś tej biblioteki wogóle nie włączył do projektu. Aplikacja nie przechowuje tych dołączanych bibliotek, one są potrzebne do zbudowania elementów aplikacji, same w sobie nie są do aplikacji dołączane. Poza tym wiele elementów aplikacji jest przechowywanych w systemowym API i to stamtąd są pobierane po uruchomieniu aplikacji.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Mironas » poniedziałek, 12 sierpnia 2013, 14:34

Ale ja nie chcę wylistować wartości wszystkich możliwych enumeratorów (typów wyliczeniowych) tylko dowolnie wybranego enumeratora (z tych zainkludowanych).

Cyfrowy Baron napisał(a):Przecież jeżeli chcesz pobrać te dane z aplikacji to taki obiekt klasy musi istnieć w tej aplikacji.

Można go utworzyć:
KOD cpp:     UKRYJ  
TAlign Align;

Tylko oczywiście musiałbym najpierw uzyskać typ TAlign ze stringa "TAlign" - i to jest mój problem.

Wracając do pierwszego postu - problem miałbym rozwiązany gdyby dało się uzyskać TPropInfo lub TTypeInfo na podstawie stringa zawierającego nazwę typu (np.: TAlign)
KOD cpp:     UKRYJ  
  String enumtype = "TAlign";

  TPropInfo* PI = Xxxxx(enumtype);
  // lub
  TTypeInfo* TI = Yyyyy(enumtype);
 

Ale jeśli to niewykonalne to trudno. Przepiszę sobie wszystkie potrzebne mi wartości z plików nagłówkowych do zasobów programu z nich będę korzystał.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Cyfrowy Baron » poniedziałek, 12 sierpnia 2013, 18:05

Mironas napisał(a):Wracając do pierwszego postu - problem miałbym rozwiązany gdyby dało się uzyskać TPropInfo lub TTypeInfo na podstawie stringa zawierającego nazwę typu (np.: TAlign)


To nie jest klasa, lecz typ wyliczeniowy będący elementem jakiejś klasy, czyli jej właściwością, a TPropInfo służy właśnie do odczytu właściwości obiektu. Zajrzałeś do pliku pomocy:

KOD text:     UKRYJ  
TPropInfo is a record of component property type information.
TPropInfo is principally used to hold the results of a call to GetPropInfo. It provides meta details about a component property as part of Delphi's RTTI (Run Time Type Information) mechanism, giving run time component property processing. This allows for more generalised component handling that avoids excessive hard coded values.


Nie możesz przekazać do tej klasy typu wyliczeniowego lecz komponent co jest wyraźnie napisane. TTypeInfo zaś przechowuje tylko informacje o typie danych więc tym bardziej nie przekażesz tam typu wyliczeniowego.



Zapytam z czystej ciekawości: do czego to się może przydać?
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Listowanie dostępnych wartości dla dowolnego enumeratora

Nowy postprzez Mironas » poniedziałek, 12 sierpnia 2013, 18:34

Sorki - pomyliłem się. Miało być:
KOD cpp:     UKRYJ  
  String enumtype = "TAlign";
  TMetaClass* MC = Xxxxx(enumtype);     // a nie TPropInfo* PI
  // lub
  TTypeInfo* TI = Yyyyy(enumtype);


Cyfrowy Baron napisał(a):Zapytam z czystej ciekawości: do czego to się może przydać?

Chcę wystawić klientowi możliwość konfigurowania interfejsu w bardzo szerokim zakresie.
Avatar użytkownika
Mironas
Programista I
Programista I
 
Posty: 427
Dołączył(a): poniedziałek, 2 stycznia 2012, 19:02
Podziękował : 17
Otrzymał podziękowań: 61
System operacyjny: Windows 10
Kompilator: C++Builder 10.3 Rio
TMS Components Pack
Gadu Gadu: 0
    Windows XPChrome


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 53 gości

cron