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;
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
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í
|