O společnostiProduktyObchodPodpora
Moravské přístroje
Hlavní stránka
O společnosti
Stažení software
Stažení dokumentů
Produkty
Control Web
Strojové vidění VisionLab
Kamery DataCam a osvětlovače DataLight
Průmyslový počítačový systém DataLab
Vědecké kamery
Speciální technika
Ceník
Aktivace produktů
Služby
Školení
Zakázková řešení
Podpora
Volba kamery a objektivu pro Strojové vidění
Control Web - Ukázkové aplikace

Hlavní stránkaPodporaFAQ

Příklady
Drobné užitečné příklady a náměty.

Obsah sekce:

Univerzální MessageBox
Tip na efektivní zálohování (backup) hodnot
Archivace změn hodnot (journal) pomocí datové sekce archive
Proměnné časování přístroje
Vícerozměrná pole
Jak automaticky odhlásit uživatele?
Jak omezit počet vybraných položek v přístroji multi_switch v módu check_box.
Jak měnit barvy pro jednotlivé stavy v přístroji multi_label.
Převod bitové reprezentace reálného čísla s jednoduchou přesností na shortreal
Jak zapsat hodnotu z přístroje s jedním výstupem (control, switch, apod.) na více datových elementů?
Jak nastavit počítání čísla týdne v roce podle českých zvyklostí

Univerzální MessageBox

Potřebujete zobrazovat různá hlášení za běhu aplikace, na které musí obsluha zareagovat? Příklad MessageBox ukazuje jak na to.

Download: MessageBox.zip

Tip na efektivní zálohování (backup) hodnot

Příklad BackupOnChange.cw ukazuje jak automaticky aktivovat zálohování hodnot (backup) při změně hodnoty datového elementu.

settings
  ...
  backup
    method = on_demand;
  end_backup;
  ...
end_settings;

...

data

  var X {backuped = true};
    b1 : boolean;
    b2 : boolean {backuped = false};
    r1 : real;
    r2 : real {backuped = false};

    procedure OnScalarLogicalChange( var DataElement : boolean );
    begin
      (*
      Procedura je vyvolána vždy, když dojde ke změne skalárního booleanovského datového elementu.
      Backup() se volá jen pro datové elementy, které mají nastaven atribut backuped na true.
      *)
      if DataElement:backuped then
        Backup();
      end;
    end_procedure;

    procedure OnScalarNumericalChange( var DataElement : real );
    begin
      (*
      Procedura je vyvolána vždy, když dojde ke změne skalárního numerického datového elementu.
      Backup() se volá jen pro datové elementy, které mají nastaven atribut backuped na true.
      *)
      if DataElement:backuped then
        Backup();
      end;
    end_procedure;

  end_var;

end_data;

Poznámka:

Pokud mají být zálohovány všechny datové elementy definované v datové sekci, není třeba testovat atribut backuped. Zápis procedury se zjednoduší jen na zavolání OCL procedury Backup().

procedure OnScalarNumericalChange( var DataElement : real );
begin
  Backup();
end_procedure;

Download: BackupOnChange.cw

Archivace změn hodnot (journal) pomocí datové sekce archive

Příklad Journal.cw ukazuje možnost archivace změn hodnot (obdoba přístroje journal) pomocí datové sekce archive a událostních procedur datových sekcí. Výhodou tohoto řešení je možnost sdílet tyto události v distribuovaných aplikacích a jejich prohlížení pomocí přístroje data_viewer.

Aplikace využíva uživatelských atributů user0 a user1, kde v atributu user0 je uložen text, popisující událost a atribut user1 slouží pro uchování původní hodnoty datového elementu. Pro vyhodnocení změn hodnot datových elementů jsou použity událostní procedury datových sekcí On*Change.

  archive Journal;
    Message : string {comment = 'Message'};
    NewValue : string {comment = 'New value'};
    OldValue : string {comment = 'Old value'};
    Operator : string {init_value = 'none'; comment = 'Operator'; user0 = 'User changed'};
    DataElement : string {comment = 'Data element'};

    procedure Notify( DE, Msg, OldVal, NewVal : string );
    begin
      DataElement = DE;
      Message = Msg;
      OldValue = OldVal;
      NewValue = NewVal;
      Archive();
    end_procedure;

    procedure On_Operator_Change();
    begin
      Notify( 'Operator', Operator:user0, Operator:user1, Operator:value_string );
      Operator:user1 = Operator:value_string;
    end_procedure;

  end_archive;

  var LogVars;
    b : boolean {user0 = 'Boolean value changed'};
    r : real {user0 = 'Real value changed'};
    s : string {user0 = 'String value changed'};

    procedure OnScalarLogicalChange( var DataElement : boolean );
    begin
      Journal.Notify( DataElement:long_name, DataElement:user0, DataElement:user1, DataElement:value_string );
      DataElement:user1 = DataElement:value_string; (* Save current value to user1 atribute *)
    end_procedure;

    procedure OnScalarNumericalChange( var DataElement : real );
    begin
      Journal.Notify( DataElement:long_name, DataElement:user0, DataElement:user1, DataElement:value_string );
      DataElement:user1 = DataElement:value_string; (* Save current value to user1 atribute *)
    end_procedure;

    procedure OnScalarStringChange( var DataElement : string );
    begin
      Journal.Notify( DataElement:long_name, DataElement:user0, DataElement:user1, DataElement:value_string );
      DataElement:user1 = DataElement:value_string; (* Save current value to user1 atribute *)
    end_procedure;

  end_var;

Download: Journal.cw

Proměnné časování přístroje

Potřebujete-li u přístroje měnit periodu časování, můžete to vyřešit tak, že parametr period nastavíte na hodnotu infinite a přepíšete událostní proceduru OnActivate příslušného přístroje tak, jak je uvedeno v následujícím příkladu:

var
  Period : real {init_value = 1};
end_var;

procedure OnActivate();
begin
  pause Period;
  send self;  
end_procedure;

Download: VariableTiming.cw

Vícerozměrná pole

Control Web umožňuje pracovat pouze s jednorozměrným polem. Pokud potřebujete vícerozměné pole, můžete se inspirovat následujícím příkladem, který ukazuje práci s dvourozměrným polem.

  var Array;
    A1 : array[ 0..49 ] of real {comment = 'array [0..9][0..4] of real'; user0 = '9'; user1 = '4'};
    A2 : array[ 0..39 ] of real {comment = 'array [0..19][0..1] of real'; user0 = '19'; user1 = '1'};

    procedure idx( Array : array of real; x, y : integer ): cardinal;
    var
      i      : cardinal;
      lindex : integer;
      SizeX  : integer;
      SizeY  : integer;
    begin
      lindex = loindex(Array);
      SizeX = val(Array[ loindex(Array)]:user0, 10);
      SizeY = val(Array[ loindex(Array)]:user1, 10);
      if (x >= 0) and (x <= SizeX) and (y >=0 ) and (y <= SizeY) then
        return x + y * SizeX;
      else
        core.DebugOutput( 'ERROR: Index out of range. ' + Array[lindex]:name + '[' + x:s + ', ' + y:s + '] (' + Array[lindex]:name + ' : ' + Array[0]:comment + ')' );
        core.StopApplication();
      end;
    end_procedure;

    procedure GetItem( Array : array of real; x, y : cardinal ): real;
    begin
      return Array[ idx(Array, x, y ) ];
    end_procedure;

    procedure SetItem( Array : array of real; x, y : cardinal; Value : real );
    begin
      Array[ idx(Array, x, y ) ] = Value;
    end_procedure;

  end_var;

...

  procedure xy();
  var
    r : real;
  begin
    Array.SetItem( Array.A1, 1, 2, 10 );
    r = Array.GetItem( Array.A2, 9, 1, 10 );
  end_procedure;

Jak automaticky odhlásit uživatele?

Aplikace AutoLogout.cw ukazuje, jak lze vyřešit automatické odhlášení přihlášeného uživatele do aplikace v systému Control Web po definované době nečinnosti.

Jak omezit počet vybraných položek v přístroji multi_switch v módu check_box.

Jednoduchá aplikace demonstrující omezeni počtu vybraných položek v přístroji multi_switch v módu check_box.

 var
    ba : array[ 1..5 ] of boolean;
  end_var;

  multi_switch switch_1;
    const
      maxSelected = 3;
    end_const;
    static
      NoOfSelected : cardinal;
    end_static;

    owner = background;
    position = 35, 35, 59, 77;
    mode = check_box;
    item
      output = ba[1];
      text = ' Item 1';
    end_item;
    item
      output = ba[2];
      text = ' Item 2';
    end_item;
    item
      output = ba[3];
      text = ' Item 3';
    end_item;
    item
      output = ba[4];
      text = ' Item 4';
    end_item;
    item
      output = ba[5];
      text = ' Item 5';
    end_item;
    
    procedure OnIndexOutput( Index : longint; Output : boolean );
    begin
      if Output <> ba[Index] then
        if Output then
          if NoOfSelected = maxSelected then
            Output = false;
            Update(false);
          else
            NoOfSelected = NoOfSelected + 1;
          end; (* if *)
        else
          NoOfSelected = NoOfSelected - 1;
        end; (* if *)
      end; (* if *)
    end_procedure;
    
  end_multi_switch;

Download: CheckBoxRestriction.cw

Jak měnit barvy pro jednotlivé stavy v přístroji multi_label.

Pokud potřebujete zobrazovat texty a pozadí jednotlivých položek v přístroji multi_label různými barvami, můžete to udělat pomocí OCL procedur přístroje například takto:

 multi_label mlbl;
    gui
      owner = pSample;
      position = 100, 40, 60, 20;
      window
        disable = zoom, maximize;
      end_window;
    end_gui;
    justify = center;
    item
      expression = BoolArray[0];
      text_list
        font = font_caption;
        text = 'Text 1';
      end_text_list;
    end_item;
    item
      expression = BoolArray[1];
      text_list
        font = font_caption;
        text = 'Text 2';
      end_text_list;
    end_item;
    item
      expression = BoolArray[2];
      text_list
        font = font_caption;
        text = 'Text 3';
      end_text_list;
    end_item;
    item
      expression = BoolArray[3];
      text_list
        font = font_caption;
        text = 'Text 4';
      end_text_list;
    end_item;

    procedure OnStartup();
    begin
      send self;
    end_procedure;

    procedure OnIndex( Index : longint );
    begin
      switch Index of
      case 1;
        SetColor( 'ink', 'white' );
        SetColor( 'paper', 'lred' );
      case 2;
        SetColor( 'ink', 'lyellow' );
        SetColor( 'paper', 'lgreen' );
      case 3;
        SetColor( 'ink', 'lcyan' );
        SetColor( 'paper', 'lblue' );
      case 4;
        SetColor( 'ink', 'lred' );
        SetColor( 'paper', 'black' );
      end; (* switch *)
    end_procedure;

  end_multi_label;

Download: multi_label_ChangeColor.cw

Převod bitové reprezentace reálného čísla s jednoduchou přesností na shortreal

Bitová reprezentace reálného čísla s jednoduchou přesností ve formátu definovaném podle IEEE 754 je následující:

Pro reprezentovanou hodnotu reálného čísla R platí:

Příklad převodu:

procedure BytesToFloat( b0, b1, b2, b3 : shortcard ): shortreal;
var
  b, e, m, s : longcard;
  E, M       : real;
  i          : integer;
begin
  b = bitshl( b3, 24 ) + bitshl( b2, 16 ) + bitshl( b1, 8 ) + b0;
  m = bitand(b, val('7FFFFF', 16 ));
  e = bitshr(bitand(b, val('7F800000', 16 )), 23);
  s = bitget(b, 31);
  for i = 0 to 7 do
    E = E + bitget( e, i ) * pow( 2, i );
    M = M + bitget( m, 23 - i ) * pow( 2, -i );
  end;
  for i = 8 to 23 do
    M = M + bitget( m, 23 - i ) * pow( 2, -i );
  end;
  if (E >= 1) and (E <=254) then
    return pow(-1, s) * pow( 2, E-127) * (1 + M); (* basic format *)
  elsif (E = 0) and (M <> 0) then
    return pow(-1, s) * pow( 2, -126) * M; (* denormalized number *)
  elsif (E = 0) and (M = 0) then
    return 0;
  elsif (E = 255) and (M = 0) then
    if s = 0 then
      return MaxShortReal; (* plus infinity *)
    else
      return MinShortReal; (* minus infinity *)
    end;
  else (* (E = 255) and (M > 0) *)
    core.DebugOutput( 'ERROR: Invalid number mask' );
    core.StopApplication();
  end;
end_procedure;

Download: Float to-from Four Bytes Conversion (IEEE754 format).cw

Jak zapsat hodnotu z přístroje s jedním výstupem (control, switch, apod.) na více datových elementů?

Tyto přístroje mají událostní proceduru OnOutput, která je vyvolávána vždy po zadání hodnoty. Do této procedury je v parametru Output předávána právě zadaná hodnota, kterou pak můžeme jednoduše přiřadit na příslušné datové elementy.

Příklad:

control MyControl;

  procedure OnOutput( Output : real );
  begin
    data_element1 = Output;
    data_element2 = Output;
    data_element3 = Output > 50;
    ...
    data_elementN = k1 + Output * k2;
  end_procedure;

end_control;  

Jak je vidět na příkladu, lze takto na datové elementy přířadit i hodnotu získanou vyčíslením výrazu.

Jak nastavit počítání čísla týdne v roce podle českých zvyklostí

Pokud potřebujete prohlížet archivy sledovaných veličin v přístroji data_viewer, máte možnost nastavit počátek časové osy dialogem. Datum a čas lze zadat ručně vepsáním do editačních polí, nebo lze otevřít pomocný dialog s kalendářem pro výběr dne. Možná Vás zarazilo, že v zobrazeném kalendáři „nesedí“ čísla týdnů. Problém je v tom, že kalendář respektuje nastavení operačního systému a pokud toto není pro dané národní prostředí správné, nesouhlasí číslování týdnů.

Číslování týdnů není podle všeobecně užívaného pravidla

Číslování týdnů není podle všeobecně užívaného pravidla

Sjednat nápravu nelze prostřednictvím okna regionálních nastavení. Ačkoliv máte nastaveno české prostředí, číslování týdnů v roce nemusí odpovídat. Příčinou je chybně nastavená položka LOCALE_IFIRSTWEEKOFYEAR tzv. locale nastavení (více informací viz MSDN ). Opravit nastavení lze např. pomocí programu Regedit, kdy v klíči HKEY_CURRENT_USER\Control Panel\International nastavíte položku iFirstWeekOfYear na hodnotu 2. Od tohoto okamžiku bude výpočet proveden podle běžných českých zvyklostí a bude stejný jako např. v tištěných kalendářích.

Číslování podle českých zvyklostí

Číslování podle českých zvyklostí

 
 | O společnosti | Produkty | Podpora | Stažení software | Stažení dokumentů | 
Moravské přístroje, a.s., Masarykova 1148, Zlín-Malenovice, 76302