end;
R = record
va: integer;
sgn: char;
end;
Stack = class(TComponent)
private
ar: array[1..100]of R;
top: integer;
protected
procedure push(vr: R);
function pop: R;
public
constructor create(AOwner: TComponent);
destructor Destroy;
function show(n:integer):R;
property Depth: integer read top;
end;
LetterBefore=(lbNone, lbDig, lbSign, lbLBr, lbRBr);
OperationMode=(omBOS, omNorm, omEOS);
OperandNumber=(onFirst, onSecond);
var
Form1: TForm1;
buf: Stack;
lb: LetterBefore;
implementation
{$R *.dfm}
constructor Stack. create(AOwner: TComponent);
begin
inherited create(AOwner);
top:=0
end;
destructor Stack. Destroy;
begin
inherited destroy
end;
procedure Stack. push(vr: R);
begin
if top<100
then begin
top:=top+1;
ar[top]:=vr
end
else
end;
function Stack. pop: R;
begin
if top>0 then begin
result:=ar[top];
top:=top-1
end
else raise Exception. Create('Stack is empty!')
end;
function Stack. show(n:integer):R;
begin
result:=ar[n]
end;
procedure TForm1.Button1Click(Sender: TObject);
var i, n, fdig, ldig: integer; result: integer;wr: R;
function SelectDigit: integer;
begin //involve sign of the number
if(fdig>2)and((eExpression. text[fdig-1]='-')or(eExpression. text[fdig-1]='+'))
and((eExpression. text[fdig-2]='-')or(eExpression. text[fdig-2]='+')
or(eExpression. text[fdig-2]='*')or(eExpression. text[fdig-2]='/')
or(eExpression. text[fdig-2]='('))
or(fdig=2)and ((eExpression. text[1]='-')or(eExpression. text[1]='+'))
then fdig:=fdig-1;
result:=StrToInt(copy(eExpression. text, fdig, ldig-fdig+1))
end;
function Calc(n, m: integer; s: char): integer;
begin
if s='+'then result:=n+m
else result:=n-m
end;
procedure Alloc(v: integer;s: char);//sign upon digit
var vp: integer; sp: char;
begin
1: wr:=buf. pop;
2: if wr. sgn='*'
3: then if s='*'//sgn='*'
4: then wr. va:=wr. va*v
5: else begin //s='+' or '-'
6: vp:=wr. va*v;
7: wr:=buf. pop;//delete multiplicative cell
8: wr. va:=Calc(wr. va, vp, wr. sgn)//update last cell
9: end
10: else if s='*'//sgn='+' or '-'
11: then begin
12: buf. push(wr);//additive part is restored
13: wr. va:=v
14: end
15: else wr. va:=Calc(wr. va, v,wr. sgn);
16: wr. sgn:=s;
17: buf. push(wr)
end;
procedure Sab(c: char);//sign upon bracket
var vp: integer;
begin
1: wr:=buf. pop;
2: if wr. sgn='*'
3: then if not(c='*')//'+' or '-'
4: then begin
5: vp:=wr. va;
6: wr:=buf. pop;//delete bracket cell
7: wr. va:=Calc(wr. va, vp, wr. sgn)//update last cell
8: end;
9: wr. sgn:=c;
10: buf. push(wr)
end;
procedure spin(i: integer; c: char);
var vp: integer;
begin
1: case c of
2: '(': if(lb=lbNone)or(lb=lbSign)or(lb=lbLBr)
3: then begin
4: with wr do begin va:=0; sgn:= '+'end;
5: buf. push(wr);//create new additive cell
6: lb:=lbLBr;
7: end
8: else raise Exception. Create('Wrong sequence!');
9: ')','F': begin
10: wr:=buf. pop;
11: if wr. sgn='*'
12: then begin //sgn='+' or '-'
13: if lb=lbDig then vp:=wr. va*SelectDigit
14: else vp:=wr. va;
15: wr:=buf. pop;
16: wr. va:=Calc(wr. va, vp, wr. sgn)
17: end
18: else if lb=lbDig then wr. va:=Calc(wr. va, SelectDigit, wr. sgn);
19: if c=')'then begin
20: vp:=wr. va;
21: wr:=buf. pop;
22: if wr. sgn='*'then wr. va:=wr. va*vp
23: else begin
24: buf. push(wr);//restore cell to create
25: wr. va:=vp;//cell for case of future
26: wr. sgn:='*'//multiplication
27: end;
28: lb:=lbRBr
29: end;
30: buf. push(wr)
31: end;
32: '+','-','*':
32: begin
33: if((c='*')or(c='/'))and((lb=lbNone)or(lb=lbLBr))then raise Exception. Create('wrong input digit');
34: if lb=lbDig then Alloc(SelectDigit, c);
35: if lb=lbRBr then Sab(c);
36: lb:=lbSign
37: end;
38: '0','1','2','3','4','5','6','7','8','9':
39: begin
40: if(lb=lbNone)or(lb=lbSign)or(lb=lbLBr)
41: then begin
42: fdig:=i;
43: ldig:=i;
44: lb:=lbDig
45: end
46: else ldig:=i;
47: if lb=lbRBr then raise Exception. Create('Wrong sign sequence'+ ' '+IntToStr(i));
48: end
49: end//case
end;
begin
buf:=Stack. create(self);
with wr do begin va:=0; sgn:= '+'end;
buf. push(wr);
lb:=lbNone;
try
for i:=1to length(eExpression. text)do spin(i, eExpression. text[i]);
if(lb=lbDig)or(lb=lbRBr)
then
else raise Exception. Create('wrong end of input'+ ' '+IntToStr(i));
spin(i,'F');
eValue. text:=IntToStr(buf. pop. va);
if buf. Depth>1then raise Exception. Create('wrong end of input!')
except
on E: Exception do begin showmessage(E. message);buf. Destroy end
end
end;
end.
4.3. Доказательство корректности программы uWert
Концепция программы состоит в следующем:
1) исходное РАВ обрабатывается в цикле литера за литерой по одной литере на каждом шаге цикла, без возвратов,
2) рабочая информация накапливается в стеке и переменных fdig, ldig и lb,
3) ячейка стека содержит промежуточный результат вычисления или его часть,
4) переменные fdig и ldig – это номера первой и последней литеры “текущего” нумерала, то есть нумерала, в пределах которого находится переменная цикла,
5) переменная lb хранит литеру, предшествующую “текущей”, то есть литере, номер которой в исходном РАВ совпадает со значением переменной цикла.
Для более формального исследования программы и доказательства её корректности далее приведён ряд определений.
“Мультипликативное окончание” М(X) для РАВ X определяется индукцией по построению X:
I. База индукции.
1.1. Если X – нумерал, то M(X) = ‘’ (то есть, мультипликативное окончание отсутствует).
1.2. Если X = m*n, где m и n – нумералы, то M(X) = X.
II. Шаг индукции:
2.1. М((X)) = (X), (то есть, РАВ (X) совпадает со своим мультипликативным окончанием).
2.2. M(Y+Z) = M(Z).
2.3. M(Y-Z) = M(Z).
2.4. M(Y*Z) = M(Y)*Z, если M(Z) = Z, иначе M(Y*Z) = M(Z).
Очевидно, что если M(X) не пусто, то М(X) является РАВ.
Мультипликативным называется РАВ, совпадающее со своим окончанием.
Выражение X\Y определено, если только существует такое Z, что X=ZY и тогда X\Y = Z.
Функция F(X) от регулярного арифметического выражения (РАВ) определяется по индукции:
I. База индукции. Если ‘X’ - нумерал, то F(X) = StrToInt(‘X’).
II. Шаг индукции:
2.1. Если X и Y являются РАВ, то
F(X+Y) = F(X)+F(Y),
F(X-Y) = F(X)-F(Y).
2.2. F(X*Y) = F(X)*F(Y), если M(X) = X и M(Y) = Y,
иначе F(X*Y) = F(X*Y\M(Y))+F(M(Y)).
F от пустой строки равно 0.
Теорема 1. Пусть программа uWert (далее просто Программа) применяется к слову eExpression. Text = ‘AXB’, где X – РАВ, а B – строка, которая может быть пустой, и приступает к выполнению процедуры spin в цикле при i = length(‘A’)+1, причём:
a) lb = lbNone, если A пуста, или lb = lbSign или lb = lbLBr, в противном случае,
b) стек buf содержит последовательность ячеек r1, …, rk, и ячейка rk содержит число n и знак операции ‘+’ или ‘-’.
Тогда на шаге i = length(‘AX’) цикла на выходе процедуры spin установится одно из следующих состояний.
lb = lbDig,
переменные fdig и ldig указывают начало и, соответственно, конец нумерала m, завершающего X,
стек buf содержит последовательность ячеек r1, …, rk, и ячейка rk содержит число n + F(X\m) и прежний знак операции ‘+’ или ‘-’.
lb = lbDig,
переменные fdig и ldig указывают начало и, соответственно, конец нумерала m, завершающего X,
стек buf содержит последовательность ячеек r1, …, rk, rk+1, ячейка rk содержит число n + F(X\S) и прежний знак операции, а rk+1 содержит число F(S\m) и знак операции ‘*’, при этом S – мультипликативное окончание X. Если X – мультипликативное РАВ, то F(X\S)=0.
Случай С.
lb = lbRBr,
стек buf содержит последовательность ячеек r1, …, rk, rk+1, ячейка rk содержит число n+ F(X\S) и прежний знак операции, а rk+1 содержит число F(S) и знак операции ‘*’, при этом S – мультипликативное окончание X. Если X – мультипликативное РАВ, то F(X\S)=0.
Доказательство. Проводится индукцией по построению X как РАВ.
I. База индукции. Пусть X - нумерал (то есть последовательность цифр без знака и без пробелов).
Тогда Программа выполнит length(‘X’) шагов цикла, в которых будут работать строкипроцедуры spin, переменные fdig и ldig установится на начало и, соответственно, конец строки X, а lb будет устанавливаться равным lbDig на всех шагах до шага length(‘X’) включительно. Стек не изменяется. То есть, реализуется случай А.
II. Шаг индукции.
2.1. Пусть X = (Y), где Y – РАВ.
Тогда в результате выполнения строк 2 – 7 процедуры spin в стек будет добавлена ячейка rk+1, содержащая число 0 и знак ‘+’, и, таким образом, перед следующим выполнение шага цикла для Y установятся условия данной леммы, причём lb = lbLBr, B = ‘)B’. По предположению индукции Программа выполнит length(Y) шагов цикла и на последнем из них на выходе из процедуры spin установится состояние, соответствующее одному из 3 указанных случаев.
Пусть реализован случай А.
Тогда на следующем шаге цикла в результате выполнения строк 18 – 26 к числу в ячейке rk+1 будет прибавлено число m и установлен знак операции ‘*’. Эта ячейка будет содержать F(‘X). В строке 28 переменной lb будет присвоено значение lbRBr, то есть, в данном случае при обработке (X) реализуется случай C.
Пусть реализован случай В.
Тогда на следующем шаге цикла в результате выполнения строк 13, 15 и 16 ячейка rk+2 снимается со стека, число из ячейки rk+2 умножается на число m, со стека снимается ячейка rk+1 и произведение складывается с её содержимым. Затем в строке 21 снимается ячейка rk, но поскольку в ней указана аддитивная операция, в строке 24 она возвращается в стек, в строке 30 в стек вводится ячейка rk+1, а строки 25 и 26 обеспечивают в ней вычисленную в строке 16 сумму и знак умножения.
Таким образом, в данном случае при обработке (X) реализуется случай C.
Пусть реализован случай C.
Тогда на следующем шаге цикла в результате выполнения строки 10 ячейка rk+2 снимается со стека, и число из неё в строке 14 временно сохраняется. Затем в строке 15 со стека снимается ячейка rk+1, и в строке 16 число из ячейки rk+1 складывается с сохранённым числом – результатом обработки X и в строке 20 временно сохраняется. Затем в строке 21 со стека снимается ячейка rk, но поскольку в ней указана аддитивная операция, в строке 24 она возвращается в стек, в строке 30 в стек вводится ячейка rk+1, а строки 25 и 26 обеспечивают в ней сохранённое число и знак умножения.
Таким образом, в данном случае при обработке (X) реализуется случай C.
2.2. Пусть X= YwZ, где Y и Z – РАВ, а w – ‘+’ или ‘-’.
Тогда применим индукционное предположение к Y и рассмотрим случаи.
Пусть реализован случай А.
Тогда на следующем шаге цикла в результате выполнения строки 35 вызывается процедура Alloc. В ней в строке 15 число, выделенное значениями переменных fdig и ldig, складывается с числом в ячейке rk. В результате число в ячейке rk становится равным n+F(X). Строки 1, 16 и 17 обеспечивают занесение его в эту ячейку Переменная lb устанавливается равной lbSign.
Пусть реализован случай B.
Тогда на следующем шаге цикла в результате выполнения строки 35 вызывается процедура Alloc. В ней в строке 6 число, выделенное значениями переменных fdig и ldig, умножается на число в ячейке rk+1, а в строках 7 и 8 складывается с числом из ячейки rk. Строки 1, 16 и 17 обеспечивают занесение суммы в эту ячейку и установку в ней w как знака операции. В результате число в ячейке rk становится равным n+F(X). Переменная lb устанавливается равной lbSign.
Пусть реализован случай С.
Тогда на следующем шаге цикла в результате выполнения строки 36 вызывается процедура Sab. В ней в строке 7 число, сформированное в ячейке rk, складывается с числом или вычитается из числа, сформированного в ячейке rk+1. В результате число в ячейке rk становится равным n+F(X). Переменная lb устанавливается равной lbSign.
Далее Программа применяется к Z и по предположению индукции Программа переходит к одному из случаев, определённых в формулировке леммы.
Пусть при обработке Z реализован случай А.
Тогда переменные fdig и ldig указывают начало и, соответственно, конец нумерала m, завершающего Z и, следовательно, строки Y+Z. Переменная lb будет равна lbDig. Стек имеет rk ячеек, и последняя из них содержит n+F(Y)+F(Z\m) = n+F(Y+Z\m). То есть, при обработке Y+Z реализован случай А.
Пусть при обработке Z реализован случай B.
Тогда cтек имеет rk+1 ячеек. Переменная lb будет равна lbDig. Ячейка rk содержит число n+F(Y)+F(Z\M(Y\m)) = n+F(Y+Z\M(Y\m) в обозначениях случая А. Ячейка rk+1 содержит число F(M(Z\m)) = F(M(Y+Z\m)). То есть, при обработке Y+Z реализован случай B.
Пусть при обработке Z реализован случай С.
Тогда cтек имеет rk+1 ячеек. Переменная lb будет равна lbRBr. Ячейка rk содержит число n+F(Y)+F(Z\M(Y)) = n+F(Y+Z\M(Y) в обозначениях случая А. Ячейка rk+1 содержит число F(M(Z)) = F(M(Y+Z)). То есть, при обработке Y+Z реализован случай С.
2.3. Пусть X=Y*Z. Рассмотрим представление (разложение) X = Y*Z\M(Y*Z)+M(Y*Z).
Если обе части разложения не пусты, то применим к ним предположение индукции п.2.2 теоремы.
Рассмотрим случай, когда M(Y*Z) пусто. Тогда существуют такое РАВ Q и число m, что Y*Z =Q+m. Применим к ним предположение индукции п.2.2 теоремы.
Рассмотрим случай, когда Y*Z\M(Y*Z) пусто, то есть, Y*Z – мультипликативный РАВ.
Тогда применим Программу к Y, как в п.2.2. Тогда после обработки Y* Программа придёт в следующее состояние. Переменная lb = lbSign, стек содержит rk+1 ячеек, в ячейке rk содержится исходное число n. Ячейка rk+1 содержит число F(X), а знак является знаком операции умножения.
Рассмотрим применение в этих условиях Программы к Z индукцией по построению Z.
I. База индукции.
1.1. Пусть Z является нумералом m. Тогда на выходе из его обработки переменные fdig и ldig указывают начало и, соответственно, конец этого нумерала. Стек содержит те же rk+1 ячеек. Число в ячейке rk+1 F(X) = F(Y) = F(Y*m\m) = F(X\m). То есть, выполняются условия случая B.
1.2. Пусть Z является (Y). Тогда нетрудно убедиться, как в п.2.1 выше, после обработки Программой такого Z установятся условия случая C. Число в ячейке rk+1 F(X) = F(Y)*F(Z)=D(Y*Z).
II. Шаг индукции. Пусть X=Y*Z*m.
2.1. Пусть X=Y*Z*m. По предположению индукции после обработки Y*Z установятся условия теоремы. Применяя рассуждения п.1.1, можно убедиться, что после обработки m установятся условия случая B. Число в ячейке rk+1 F(X\m) = F(Y*Z*m\m) = F(Y)*F(Z*m\m).
2.2. Пусть X=Y*Z*(U). По предположению индукции после обработки Y*Z установятся условия теоремы. Применяя рассуждения п.1.2, можно убедиться, что после обработки (U) установятся условия случая C. Число в ячейке rk+1 F(X) = F(Y*Z*(U)) = F(Y)*F(Z)*F(U)) = F(Y)*F(Z*(U)).
Теорема доказана.
Следствие. Если программу uWert применить к РАВ X, то в качестве результата будет получено число F(X).
Доказательство. Пусть Программа применяется к РАВ X. Нетрудно убедиться, что при входе в цикл выполняются условия Теоремы 1, причём стек содержит одну ячейку, то есть, k=1, n=0 и z=’+’. Поэтому Программа выйдет из цикла и перейдёт к процедуре spin(i, ‘F’) , установив один из 3 случаев состояния, указанных в Теореме.
Рассмотрим действия процедуры spin(i, ‘F’) в каждом из этих случаев.
В строке 18 число в ячейке 1 складывается с числом в конце X. В результате это число становится равным F(X).
Случай B.
Стек содержит 2 ячейки. Строка 13 умножает число из ячейке 2 на число в конце X. Затем в строках 15 и 16 произведение складывается с числом в ячейке 1, а ячейка 2 выводится из стека. В результате единственная ячейка стека содержит F(X).
Случай C. Стек содержит 2 ячейки. Строка 14 временно сохраняет число из ячейки 2. Затем в строках 15 и 16 оно складывается с числом в ячейке 1, а ячейка 2 выводится из стека. В результате единственная ячейка стека содержит F(X).
Число из ячейки стека выводится в окно eValue.
Что и требовалось доказать.
УПРАЖНЕНИЯ
1. Оцените конструктивную сложность программы по M. Холстеду.
2. Оцените вычислительную сложность программы.
5. ОРГАНИЗАЦИЯ МНОГООКОННОГО ИНТЕРФЕЙСА И ДИАЛОГА В ПРИЛОЖЕНИЯХ
5.1. Многооконный интерфейс на основе сохраняемых форм
5.2. Диалог на основе динамически создаваемых форм
5.2.1. Проект диалоговой функции в Delphi
unit CyrDialog;
interface
////////////////////////////////////////////////////////////////////////////////
//* Модуль обеспечивает диалог приложения с пользователем
//* и для этой цели предоставляет функцию Rudial, аналогичную
//* функции MessageDLG. Отличие состоит в том, что Rudial
//* показывает кнопки с русскязычными надписями.
uses classes, forms, dialogs, stdctrls, controls;
type TDForm = class(TCustomForm)end;
function Rudial(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Word;
var vform: TDForm;
implementation
uses math, graphics, windows, sysutils;
function Rudial(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint): Word;
var vbut: TButton; vt: TLabel; i, n: integer;
ab: array [1..11]of string; mr: array [1..11]of TModalResult;
begin
n:=0;
if mbOK in Buttons then begin inc(n); ab[n]:='О''КЭЙ'; mr[n]:=mrOK end;
if mbYes in Buttons then begin inc(n); ab[n]:='ДА'; mr[n]:=mrYES end;
if mbNO in Buttons then begin inc(n); ab[n]:='НЕТ'; mr[n]:=mrNO end;
if mbCancel in Buttons then begin inc(n); ab[n]:='ОТМЕНА'; mr[n]:=mrCancel end;
if mbAbort in Buttons then begin inc(n); ab[n]:='БАСТА'; mr[n]:=mrAbort end;
if mbRetry in Buttons then begin inc(n); ab[n]:='ПОВТОР'; mr[n]:=mrRetry end;
if mbIgnore in Buttons then begin inc(n); ab[n]:='НУ И ЧТО'; mr[n]:=mrIgnore end;
if mbAll in Buttons then begin inc(n); ab[n]:='ВСЕ'; mr[n]:=mrALL end;
if mbNoTOALL in Buttons then begin inc(n); ab[n]:='НИКАКИЕ'; mr[n]:=mrALL+1 end;
if mbYEStoALL in Buttons then begin inc(n); ab[n]:='ВСЕ'; mr[n]:=mrYEStoALL end;
try
vform:=TDForm. CreateNew(Application);
with vform do
begin
Height:=110;
BorderStyle:=bsDialog;
caption:='Ответьте нажатием кнопки.';
position:=poScreenCenter;
BorderWidth:=3;
FormStyle:=fsStayOnTop;
vt:=TLabel. Create(vform);
vt. parent:=vform;
vt. AutoSize:=true;
vt. caption:=msg;
vt. Font. Style:=[fsBold];
Width:=max(vt. width+50,70*n+24*(n-1)+50);
vt. top:=10;
vt. left:=(width-vt. width)div 2;
for i:=1to n do
begin
vbut:=TButton. Create(vform);
with vbut do
begin
parent:=vform;
top:=40;
width:=70;
height:=23;
left:=(vform. width-70*n-20*(n-1))div 2+(i-1)*(70+20);
Caption:=ab[i];
font. style:=[fsBold];
ModalResult:=mr[i]
// onClick:=CliRu
end
end;
result:=ShowModal;
FreeAndNil(vform)
end
finally
if not(vform=nil)then vform. free
end
end;
{procedure TDForm. CliRu(sender: TObject);
begin
TForm(TComponent(sender).owner).close
end;}
end.
5.2.2. Проект диалоговой функции в Microsoft Visual Studio 2008 (CLR, язык C#)
В среде проектирования включение дополнительных форм в проект обеспечивается в главном меню командами Проект – Добавить форму Windows …. В результате открывается окно выбора элемента, в котором уже выбран пункт “Форма Windows Form”. Пользователю достаточно нажать экранную кнопку Добавить. В это же окно можно попасть, активируя другие подпункты пункта главного меню Проект, начинающиеся со cлова Добавить.
В проект будет добавлены файлы с именем новой формы и расширением cs и Designer. cs. К новой форме можно обращаться при запуске приложения, выполнив предложения:
System. Windows. Forms. Form vbox;//объявление переменной
vbox = new NBox();//создание экземпляра формы.
Далее её можно сделать, например, сделать видимой на равне с главной формой предложением:
vbox. Show ();
или видимой в модальном режиме, то есть в режиме вызова (с приостановкой активности вызывающей формы:
vbox. ShowDialog();
Кроме того форму можно определить и использовать без “дизайнера”, то есть отдельного модуля, обеспечивающего хранение содержимого формы и заполнение её при запуске. Для этого достаточно определить соответствующий класс и вызывать его конструктор, а заполнение формы обеспечивать по месту этого вызова. Такой случай показан в нижеследующем приложении.
Главная форма:
using System;
using System. Collections. Generic;
using ponentModel;
using System. Data;
using System. Drawing;
using System. Linq;
using System. Text;
using System. Windows. Forms;
namespace WinForm12
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
NBox. PseudoFun();
// this. Close();
}
}
}
Наряду с главной формой Form1 в проекте имеется модуль NewBox. cs:
using System;
using System. Windows. Forms;
//using NUnit. Framework;
namespace WinForm12
{
public class NBox : Form
{
public static void PseudoFun()
{
// MessageBox. Show("bingo!");
System. Windows. Forms. Form vbox;
vbox = new NBox();
vbox. Name = "NBox";
System. Windows. Forms. Button vbut;
vbut = new System. Windows. Forms. Button();
// vbut. Show();
vbut. Location = new System. Drawing. Point(100, 100);
vbut. Size = new System. Drawing. Size(100,30);
vbut. Text = "ЖМИ";
vbox. Controls. Add(vbut);
// vbut. Click += new EventHandler(NBox. vbut_Click);
vbut. Click += NBox. vbut_Click;
vbox. ShowDialog();
}
public void Main()
{
MessageBox. Show("bingo!");
}
public NBox()
{
InitializeForm();
}
private void InitializeForm()
{
this. Text = "Nbox";
}
private static void vbut_Click(object sender, EventArgs e)
{
// System. Windows. Forms. Button lbut;
// lbut = sender as Button;
// System. Windows. Forms. Form lbox;
// lbox = lbut. Parent as Form;
// MessageBox. Show(lbox. Text);
// lbox. Close();
((sender as Button).Parent as Form).Close();
}
}
}
В этом модуле содержится класс NBox, определяющий форму и включающий в себя статический метод PseudoFun, который создаёт экземпляр формы NBox, заносит на неё кнопку и обработчик её нажатия и вызывает форму в модальном режиме.
using System;
using System. Windows. Forms;
namespace WinForm12
{
public class NBox : Form
{
public static void PseudoFun()
{
System. Windows. Forms. Form vbox;
vbox = new NBox();
vbox. Name = "NBox";
System. Windows. Forms. Button vbut;
vbut = new System. Windows. Forms. Button();
vbut. Location = new System. Drawing. Point(100, 100);
vbut. Size = new System. Drawing. Size(100,30);
vbut. Text = "ЖМИ";
vbox. Controls. Add(vbut);
// vbut. Click += new EventHandler(NBox. vbut_Click);
vbut. Click += NBox. vbut_Click;
vbox. ShowDialog();
}
public NBox()
{
InitializeForm();
}
private void InitializeForm()
{
this. Text = "Nbox";
}
private static void vbut_Click(object sender, EventArgs e)
{
// System. Windows. Forms. Button lbut;
// lbut = sender as Button;
// System. Windows. Forms. Form lbox;
// lbox = lbut. Parent as Form;
// lbox. Close();
((sender as Button).Parent as Form).Close();
}
}
}
5.2.3. Проект диалоговой функции в Microsoft Visual Studio 2008 (CLR, язык C++)
Приложение, аналогичное последнему, рассмотренному в предыдущем разделе, можно построить в той же среде проектирования, но для языка C++.
В этом случае проект содержит главный файл с расширением cpp, а именно:
CLRWin02.cpp: главный файл проекта.
#include "stdafx. h"
#include "TestForm. h"
using namespace CLRWin02;
int nn=25;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Включение визуальных эффектов Windows XP до создания каких-либо элементов управления
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Создание главного окна и его запуск
Application::Run(gcnew TestForm());
return 0;
}
Модуль NewBox. h, содержащий определение формы, которая динамически создавается и вызывается в модальном режиме из модуля TestForm. h.
#pragma once
#include "NewBox. h"
namespace CLRWin02 {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Сводка для Form1
///
/// Внимание! При изменении имени этого класса необходимо также изменить
/// свойство имени файла ресурсов ("Resource File Name") для средства компиляции управляемого ресурса,
/// связанного со всеми файлами с расширением .resx, от которых зависит данный класс. В противном случае,
/// конструкторы не смогут правильно работать с локализованными
/// ресурсами, сопоставленными данной форме.
/// </summary>
public ref class TestForm : public System::Windows::Forms::Form
{
public:
TestForm(void)
{
InitializeComponent();
//
//TODO: добавьте код конструктора
//
}
protected:
/// <summary>
/// Освободить все используемые ресурсы.
/// </summary>
~TestForm()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::MenuStrip^ menuStrip1;
protected:
private: System::Windows::Forms::ToolStripMenuItem^ testToolStripMenuItem;
private:
/// <summary>
/// Требуется переменная конструктора.
/// </summary>
System::ComponentModel::Container ^components;
#pragma region Windows Form Designer generated code
/// <summary>
/// Обязательный метод для поддержки конструктора - не изменяйте
/// содержимое данного метода при помощи редактора кода.
/// </summary>
void InitializeComponent(void)
{
this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip());
this->testToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem());
this->menuStrip1->SuspendLayout();
this->SuspendLayout();
//
// menuStrip1
//
this->menuStrip1->Items->AddRange(gcnew cli::array< System::Windows::Forms::ToolStripItem^ >(1) {this->testToolStripMenuItem});
this->menuStrip1->Location = System::Drawing::Point(0, 0);
this->menuStrip1->Name = L"menuStrip1";
this->menuStrip1->Size = System::Drawing::Size(292, 24);
this->menuStrip1->TabIndex = 0;
this->menuStrip1->Text = L"menuStrip1";
//
// testToolStripMenuItem
//
this->testToolStripMenuItem->Name = L"testToolStripMenuItem";
this->testToolStripMenuItem->Size = System::Drawing::Size(40, 20);
this->testToolStripMenuItem->Text = L"Test";
this->testToolStripMenuItem->Click += gcnew System::EventHandler(this, &TestForm::testToolStripMenuItem_Click);
//
// TestForm
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(292, 266);
this->Controls->Add(this->menuStrip1);
this->MainMenuStrip = this->menuStrip1;
this->Name = L"TestForm";
this->Text = L"TestForm";
this->menuStrip1->ResumeLayout(false);
this->menuStrip1->PerformLayout();
this->ResumeLayout(false);
this->PerformLayout();
}
#pragma endregion
private: System::Void testToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) {
PseudoFun();
};
};
}
Модуль TestForm. h содержит определение класса TestForm, содержащего пункт в главном меню, при активировании которого вызывается функция PseudoFun(), определённая в модуле NewBox.
Модуль NewBox:
namespace CLRWin02 {
using namespace System::Windows::Forms;
static void vbut_Click(System::Object^ sender, System::EventArgs^ e)
{
dynamic_cast< System::Windows::Forms::Form^ >(dynamic_cast< System::Windows::Forms::Button^ >(sender)->Parent)->Close();
};
void PseudoFun()
{
System::Windows::Forms::Form ^vForm2;
vForm2 = gcnew System::Windows::Forms::Form();
vForm2->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
vForm2->ClientSize = System::Drawing::Size(400, 200);
vForm2->Name = L"NBox";
vForm2->Text = L"Кириллизованный MessageBox";
System::Windows::Forms::Button^ vbut;
vbut = (gcnew System::Windows::Forms::Button());
vForm2->Controls->Add(vbut);
vbut->Location = System::Drawing::Point(100, 100);
vbut->Size = System::Drawing::Size(100, 30);
vbut->Text = L"ЖМИ";
vbut->UseVisualStyleBackColor = true;
vbut->Click += gcnew System::EventHandler(vbut_Click);
vForm2->ShowDialog();
}
}
Легко заметить, что в случае языка C++, не допускающего определение класса частями в нескольких модулях (как со спецификатором partial в языке C#l), фрагмент приложения, порождаемый средой проектирования автоматически и инициирующий форму, помещается в том же модуле, в котором находится определение класса, в данном случае – в модуле TestForm. h.
В проект входят вспомогательные модули:
stdafx. cpp: исходный файл, содержащий только стандартные включаемые модули
// CLRWin02.pch будет предкомпилированным заголовком
// stdafx. obj будет содержать предварительно откомпилированные сведения о типе
#include "stdafx. h"
stdafx. h: включаемый файл для стандартных системных включаемых файлов
// или включаемых файлов для конкретного проекта, которые часто используются, но
// не часто изменяются
#pragma once
TestForm. resx, app. aps, app. ico, CLRWin02.vcproj, а также
AssemblyInfo. cpp
#include "stdafx. h"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// Общие сведения об этой сборке предоставляются следующим набором
// атрибутов. Отредактируйте значения этих атрибутов, чтобы изменить
// общие сведения об этой сборке.
//
[assembly:AssemblyTitleAttribute("CLRWin02")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("Microsoft")];
[assembly:AssemblyProductAttribute("CLRWin02")];
[assembly:AssemblyCopyrightAttribute("Copyright (c) Microsoft 2010")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
//
// Сведения о версии сборки состоят из следующих четырех значений:
//
// Основной номер версии
// Дополнительный номер версии
// Номер построения
// Редакция
//
// Можно задать все значения или принять номер построения и номер редакции по умолчанию,
// используя "*", как показано ниже:
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
Главная форма и вызванное диалоговое окно выглядят на экране следующим образом;

6. ПРОЕКТИРОВАНИЕ КЛАССОВ
6.1. Основы модельно-ориентированного проектирования
Откуда берутся объекты в АСУ и бизнес-приложениях?
В настоящее время систематический подход к объектно-ориентированному проектированию представлен, главным образом, так называемым, MDA (model-driven architecture), или МОП (модельно-ориентированным проектированием). Основоположник – Rational Rose, подхватившей более 10 лет назад наработки OMG.
Идея MDA: проектирование включает в себя создание имитационной модели реальной системы ведётся на основе этой модели, и в неё же встраивается проектируемое компьютерное приложение для замены или развития её определённых функций.
Модельно-ориентированное и, соответственно, объектно-ориентированное проектирование реализуются в конкретных организационных формах в рамках определённых концепций жизненного цикла программ. Относительно независимым от этих форм и концепций является перечень “дисциплин” – видов деятельности, составляющих процесс создания программы (специальные виды технологических процессов):
бизнес-моделирование (business modeling),
работа с требованиями (анализ требований requirements),
проектирование (design),
реализация,
тестирование,
развёртывание,
конфигурирование,
управление изменениями,
управление проектом,
связь с окружением.
Дисциплины характеризуются своими результатами – “артефактами”. Основным артефактом бизнес-моделирования является имитационная модель реальной системы. Артефакты анализа требований: виденье (как бы ТЗ), описание (модель) “прецедентов”, словарь, спецификация требований, функциональных и прочих.
Артефакты анализа требований составляются на естественном языке, но, начиная с некоторого момента, желательно использование графики. Основным является использование нотации UML. Графика и текст дополняют друг друга.
Модель реальной системы отображает основные объекты моделируемой системы, их свойства и отношения. Для этой модели характерно отражение статических аспектов системы.
Динамический аспект системы отражается, главным образом, в описании прецедентов и функциональных требований. Прецедент (use case). Основной прецедент и другие.
Важным элементом бизнес-моделирования и анализа требований является определение границы системы, в модель должна определять внутренние объекты и внешние (по отношению к этой границе), с которыми они взаимодействуют.
Этап проектирования начинается принятием решения о месте создаваемой компьютерной системы в составе реальной системы. В общем случае одни объекты реальной системы ликвидируются без следа, другие преобразуются, входя внутрь компьютерной системы, третьи изменяют свои связи и свойства. В результате принятия этого решения должны быть переработаны вышеуказанные артефакты.
Последующие решения связаны с уточнением состава объектов уже внутри компьютерной системы, детализацией свойств и операций (“методов”), выбором компьютерной платформы, операционной среды и языка (системы) программирования для реализации. Все эти мероприятия создают необходимые предпосылки для перехода от проектирования к реализации.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 |


