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