Jak pobrać kategorię kontrolki na podstawie jej klasy/uchwytu?

0

Witam,

1. jak w temacie, mam PID procesu i chciałbym zassać do swojego programu w formacie JPEG/PNG ikonkę procesu. W jaki sposób mogę to zrealizować?
Ok, z tym sobie poradziłem

  1. Czy jest możliwość określenia po klasie kontrolki/uchwycie/nazwie VCL obcej aplikacji jej kategorii?
    Chodzi mi o coś takiego, że mamy w jakiejś aplikacji kontrolkę **
TButton

**, **TEdit

**, **<code class="delphi">TMemo

**, **TVirtualStringTree

**, **<code class="delphi">TListBox

**, **TCombobox

**, **<code class="delphi">TDBCombobox

** i chciałbym dowiedzieć się do jakiej kategorii należy dana klasa:

a) Lista - kontrolki zawierające listę (

TVirtualStringTree

, TListBox

)
**b)** **Combo** - kontrolki rozwijane (
```delphi
TCombobox

, TDBCombobox

)
**c)** **Button** - Przyciski (
```delphi
TButton

)
d) Text - Pola tekstowe (

TEdit

, TMemo

)

Zakładam, że customowe komponenty typu suiPack, TMS Advanced, które zawierają swoje wersje 
```delphi
TAdvListBox

, TAdvStringGrid

, <code class="delphi">TAdvEdit

zapewne dziedziczą po systemowej klasie TListBox, TStringGrid, TEdit

. Czy da się to jakoś określić korzystając z systemowych funkcji?

Ogólnie chodzi mi o uniknięcie sprawdzania każdej klasy kontrolki i zastosowaniu funkcji 
```delphi
if klasa_kontrolki in TablicaStringow_Listy then kategoria := 'Lista';
if klasa_kontrolki in TablicaStringow_Combo then kategoria := 'Combo';

itp. bo są setki klas komponentów w różnych aplikacjach, które musiałbym uwzględnić w tablicy a chciałbym to zautomatyzować i do każdej pobranej klasy kontrolki dodawać w opisie jej kategorię i przedstawiać to w postaci drzewa:

TfrmMain
Button (TButton)
Button (TsuiButton)
Button (TAdvGlowButton)
Text (TEdit)
Text (TAdvEdit)
Text (TMemo)
List (TListBox)
List (TDBListBox)
List (TTreeView)
List (TListView)
Combo (TCombobox)
Combo (TImageComboBox)
Combo (TDriveComboBox)
Panel (TPanel)
Toolbar (TToolbar)</li> </ul>
0
user322 napisał(a)

zapewne dziedziczą po systemowej klasie

TEdit i inne wymienione to nie są żadne systemowe klasy - to klasa komponentu z VCL; Poza tym nie bądź taki pewny - np. komponent pola edycyjnego wcale nie musi dziedziczyć po klasie TEdit czy TCustomEdit; Równie dobrze może być zbudowany od podstaw, dziedzicząc po klasie TWinControl czy własnej klasie bazowej; Nie masz pewności, że każdy komponent cudzych aplikacji dziedziczy z klas bazowych komponentów VCL, więc na szywno tego nie można określić, aby mieć 100% pewności;


Najprostszym rozwiązaniem jest określenie typu komponentu po prostu - po jego nazwie; Wrzuć sobie do macierzy lub listy słowa-klucze, które za pomocą np. funkcji Pos będziesz wyszukiwał w nazwie klasy; Jeśli dany klucz dopasujesz - przypisujesz klasie dany typ (nie wiem jak masz to zrobione, w każdym razie np. jakiś enum);

Dajmy przykład - mamy klucz edit; Pobierasz nazwę klasy komponentu i przekazujesz ją do funkcji walidującej; Jeśli słówko edit znajduje się w przekazanej nazwie klasy, to komponent uznajesz za pole edycyjne; Twoja funkcja walidująca poprawnie rozpozna np. klasy TEdit i TAdvEdit, TFuriousEditField itd.; Pamiętaj jednak, aby walidacja przebiegała bez rozróżniania wielkości liter;

Podobnie dla innych - słówko button dopasujesz do klas TButton, TsuiButton, TAdvGlassButton i innych przycisków;


Problem stanowić mogą nazwy klas, które nie zawierają pełnych sufiksów, np. zmyślona klasa TFuriousBtn już nie będzie pasować do klucza button; Rozwiązaniem może być dodanie większej ilości kluczy dla danego typu komponentów; Tu jednak trzeba się zorientować, bo ciężko powiedzieć, czy wszystkie istniejące klasy komponentów nazwane są sensownie.

1

Taka luźna myśl:

Type TControlPrimaryKind = (cpkButton, cpkListBox, {...});

Type TControlHelper =
     Class helper for TControl
      Public
       Function GetControlPrimaryKind: TControlPrimaryKind;
      End;

{ ... }
Function TControlHelper.GetControlPrimaryKind: TControlPrimaryKind;
Begin
 if (self is TButton) Then
  Result := cpkButton Else

 if (self is TListBox) Then
  Result := cpkListBox Else

{ ... }
End;

I potem po prostu Component.GetControlPrimaryKind() - powinno zadziałać także dla klas pochodnych, tj.TButton.GetControlPrimaryKind zwróci cpkButton.

Edit: ewentualnie zamiast is wykorzystaj metodę InheritsFrom.

3

@Patryk27 podał rozwiązanie, które sprawdza po prostu skąd klasa komponentu dziedziczy, ja natomiast podam przykładowy kod ilustrujący pomysł z poprzedniego mojego posta, który powinien rozumieć każdy znający podstawy języka:

type
  TComponentType = (ctEdit, ctMemo, ctButton, ctComboBox {, ...}, ctUnknown);

function SpecifyComponentType(AComponentName: AnsiString): TComponentType;
const
  COM_TYPE_KEYS: array [TComponentType] of AnsiString = (
    'edit',      // key for edit fields
    'memo',      // key for memos
    'button',    // key for buttons
    'combobox',  // key for combo boxes
    ''           // key for unknown
  );
var
  ctToken: TComponentType;
begin
  AComponentName := AnsiLowerCase(AComponentName);

  {$IFDEF FPC}
  for ctToken in TComponentType do
    if Pos(COM_TYPE_KEYS[ctToken], AComponentName) > 0 then
      Exit(ctToken);
  {$ELSE} { compatible with Delphi7 }
  for ctToken := Low(TComponentType) to High(TComponentType) do
    if Pos(COM_TYPES_KEYS[ctToken], AComponentName) > 0 then
    begin
      Result := ctToken;
      Exit;
    end;
  {$ENDIF}

  Result := ctUnknown;
end;

Dyrektywy kompilatora można usunąć; Przykład wywołania:

begin
  WriteLn('TButton            ', SpecifyComponentType('TButton'));
  WriteLn('TAdvButton         ', SpecifyComponentType('TAdvButton'));
  WriteLn('TAdvGlassButton    ', SpecifyComponentType('TAdvGlassButton'));
  WriteLn();
  WriteLn('TEdit              ', SpecifyComponentType('TEdit'));
  WriteLn('TAdvEdit           ', SpecifyComponentType('TAdvEdit'));
  WriteLn('TFuriousEditField  ', SpecifyComponentType('TFuriousEditField'));
  WriteLn();
  WriteLn('TFooBaldBar        ', SpecifyComponentType('TFooBaldBar'));
  ReadLn;
end.

Wyjście dla powyższych instrukcji:

TButton            ctButton
TAdvButton         ctButton
TAdvGlassButton    ctButton

TEdit              ctEdit
TAdvEdit           ctEdit
TFuriousEditField  ctEdit

TFooBaldBar        ctUnknown

Jak widać zasada bardzo prosta i działać powinna dobrze.

0

No takie rozwiązanie wydaje się być trafione i chyba nic lepszego się już nie da wymodzić, lecz występuje problem z kompilacją kodu.
Zatrzymuje się na linijce__

for ctToken in TComponentType do

i krzyczy [dcc32 Error] Repository.pas(76): E2029 Expression expected but ')' found

Używam Delphi XE3</del>

Poradziłem sobie z tym. Teraz próbuję zmodyfikować funkcję, aby zwracała string zamiast TComponentType.

Ok działa pięknie, pozostaje mi tylko teraz uzupełnić tablicę możliwymi danymi. Dzięki Wam śliczne

1 użytkowników online, w tym zalogowanych: 0, gości: 1