-
Добрый день!
Делфи начал изучать сравнительно недавно!
Проблема следующая: хочу рисовать на дочерней форме Form2 произвольную фигуру, допустим, канвой Image1 или Form2 и компилятор Делфи без конца ругается на доступ в запрешенную область. Сделал отрисовку на SDI форме, там все получается без проблем, теперь хочу перейти на MDI форму (все же более продвинуто), где в дочерней Form2 будет рабочая область, а в Form1 меню с кнопками по управлению графикой Form2 (цвет заливки, масштаб фигуры и т.д).
Форумчане, подскажите можно ли вообще рисовать на канве в дочерней форме, скажем, или может каким другим способом это можно осуществить, код в SDI уже написал. -
Омлет © (19.06.12 17:02) [1]Компилятор же человеческим языком ругается. Что именно говорит? По поводу какого кода?
А рисовать на дочерней форме можно, имея ссылку на неё. -
Cobalt © (19.06.12 17:03) [2]Как ругается компилятор - это твой самый главный секрет.
-
Ошибка появляется когда кликаю на Form2.Image1 и компилятор доходит то строчки Form2.Image1.Canvas.Brush.Color := Form1.ColorBox3.Selected; при нажатии на кнопке создания Form2
Ошибка следующая:
Project Batar7ob.exe raised exception class EAccessViolation with message 'Access violation at address 0045CF21 in module 'Batar7ob.exe'.Read of address 000002FC '. Process stopped. Use Step or Run to continue.
unit Workspace;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls;
type
TForm2 = class(TForm)
BitBtn1: TBitBtn;
Image1: TImage;
procedure BitBtn1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormActivate(Sender: TObject);
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
end;
var
Form2: TForm2;
implementation
uses Basicparty;
{$R *.dfm}
constructor TForm2.Create;
begin
inherited Create(AOwner);
end;
procedure TForm2.BitBtn1Click(Sender: TObject);
begin
Close;
end;
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
procedure TForm2.FormActivate(Sender: TObject);
begin
Form1.ColorBox1.ParentColor := True;
Form1.ColorBox2.ParentColor := True;
Form1.ColorBox3.ParentColor := True;
ColorFon := Form1.ColorBox3.Selected;
ActiveChanged; //мои попытки, сделать активной Form2 чтобы рисовалось на ней
FocusControl(Form2);
Show;
SetFocus;
Form2.Image1.Canvas.Brush.Color := Form1.ColorBox3.Selected;
Form2.Image1.Canvas.Rectangle(0,0,800,600);
ArrBatar[i] := Tbatar.Create();
ArrBatar[i].ColorFig := Form1.ColorBox1.Selected;
ArrBatar[i].ColorZal := Form1.ColorBox2.Selected;
ArrBatar[i].Scale := Form1.ComboBox1.ItemIndex;
ArrBatar[i].SetX(Form1.Width div 2) ;
ArrBatar[i].SetY(Form1.Height div 2);
ArrBatar[i].Paint(ArrBatar[i].Scale,ArrBatar[i].X0,ArrBatar[i].Y0);
ArrBatar[i].DrawText();
end;
procedure TForm2.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
deltaX,deltaY: integer;
begin
if ssLeft in Shift then // клик по левой кнопке мыши
begin
deltaX := (MyMouse.CursorPos.X-Form2.Image1.Left-4) - ArrBatar[i].X0;
deltaY := (MyMouse.CursorPos.Y-Form2.Image1.Top-32) - ArrBatar[i].Y0;
ArrBatar[i].Move(ArrBatar[i],deltaX,deltaY);
ArrBatar[i].DrawText();
end;
if ssRight in Shift then // клик по правой кнопке мыши
begin
i := i+1;
ArrBatar[i] := TBatar.create();
ArrBatar[i].Scale := Form1.ComboBox1.ItemIndex;
ArrBatar[i].ColorFig := Form1.ColorBox1.Selected;
ArrBatar[i].ColorZal := Form1.ColorBox2.Selected;
ArrBatar[i].X0 := MyMouse.CursorPos.X-Form2.Left-4;
ArrBatar[i].Y0 := MyMouse.CursorPos.Y-Form2.Top-32;
ArrBatar[i].Paint(ArrBatar[i].Scale,ArrBatar[i].X0,ArrBatar[i].Y0);
ArrBatar[i].DrawText();
Form2.Image1.Refresh; //обновляет после изменения масштаба
end;
end;
end. -
> А рисовать на дочерней форме можно, имея ссылку на неё.
Я вроде так и делаюForm2.Image1.Canvas.Brush.Color := Form1.ColorBox3.Selected;
Поправьте, пожалуйста, если, что то не так... -
Омлет © (19.06.12 22:29) [5]А переменную Form2 нигде не меняешь?
И в методах класса TForm2 можно обращаться к его полям напрямую. Т.е. вместоForm2.Image1.Canvas.Brush.Color := Form1.ColorBox3.Selected;
должно бытьImage1.Canvas.Brush.Color := Form1.ColorBox3.Selected;
Настоятельно советую учебник почитать. Вслепую ты черти что нагородил уже. -
Всмысле не меняю??
Form2 создается всякий раз при нажатии на Form1.Button2 (планирую сделать многопоточность воркспейсов) вот код создания Form2.procedure TForm1.Button2Click(Sender: TObject);
begin
j:= j+1;
Form2 := TForm2.Create(Application);
With Form2 do
begin
BorderIcons := [biSystemMenu] + [biMinimize];
Caption:= 'Workspace'+IntToStr(j);
Width := 800;
Height := 600;
Visible := True;
end;
end; -
Спасибо за совет - помогло, прошел то место, но проблема с формой не решилась... встало дальше на сточке..ArrBatar[i].X0 := MyMouse.CursorPos.X-Form2.Left-4;
Подсказка, при наводе на слово Form2, пишет Form2=nil , Form2.Left=Inaccessible value -
Омлет © (19.06.12 22:59) [8]Я же говорю - где-то затирается переменная Form2.
И, повторяю, не обращайся к переменной Form2 внутри её же методов.
ПишиArrBatar[i].X0 := MyMouse.CursorPos.X - Left - 4; -
Спасибо, заработало, как в том мульфильме))..но на половину решилась, дело в чем, в коде, который находится в процедуре (т.е вне методов Form2) procedure Tbatar.Paint(scale,X,Y:integer); появляется примерно такого содержания, Form2.Image1.Width опять Inaccessible value, вопрос куда девается переменная Form2, никак не могу найтиif (X2party > Form2.Image1.Width) or (Y2body > Form2.Image1.Height) then
begin
Showmessage('Фигура за границами экрана!');
Exit;
end; -
Омлет © (20.06.12 07:23) [10]> вопрос куда девается переменная Form2, никак не могу найти
Диссациирует втуне. -
Cobalt © (20.06.12 07:44) [11]поиск по коду рулит.
-
> Диссациирует втуне
а это как, можно поподробнее?)) -
Cobalt © (20.06.12 10:03) [13]Тебе намекают, что ты переменную обнуляешь не вовремя.
Есть такая замечательная команда в Delphi - Search->Find in files
указываешь имя переменной, поиск по всему проекту, и проверяешь где и когда ты туда что-то записываешь. -
понял) щас попробую
-
В общем прогнал по всем упоминаниям, не заметил затирания, единственно - нашел по вотч листу, что в своих методах класса Image1.Width = 810, а переменная Form2.Image1.Width = Inaccessible value, естественно, что во внешних процедурах Image1.Width =Inaccessible value, а глобальной Form2.Image1.Width то и нету... такое ощущение что, в модуле Basicparty, (так где как раз это злополучная процедура Tbatar.Paint(scale,X,Y:integer)) значение Width нету
-
Уважаемые, мастера, посмотрите, пожалуйста, может я просто неправильно прикрутил Form2 (находится в модуле Workspace) к модулю Basicparty поэтому и Form2.Image1.Width = Inaccessible valueunit Basicparty;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Workspace;
type
Tbatar = class //объявление класса батареек
private
FNazv:string;
FId:integer;
FX0:integer;
FY0:integer; //координаты опорной точки (левый верхний)
Fwidth: integer;
Fheight: integer;
FColorFig:TColor; //цвет фигуры
FColorZal:TColor; //цвет заливки фигуры
FScale: Integer; //цвет фигуры
public
procedure Paint(scale,X,Y:integer);
procedure Move(Batar: TBatar; deltaX,deltaY: integer);
procedure SetX(X:integer);
procedure SetY(Y:integer);
procedure SetScale(Sc:integer);
procedure SetColorFig(ColFig:TColor);
procedure SetColorZal(ColZal:TColor);
procedure DrawText();
constructor Create();
property Nazv: string read FNazv;
property X0: integer read FX0 write SetX;
property Y0: integer read FY0 write SetY;
property Scale: integer read FScale write SetScale;
property Width: integer read Fwidth;
property Height: integer read Fheight;
property ColorFig: TColor read FColorFig write SetColorFig;
property ColorZal: TColor read FColorZal write SetColorZal;
end;
TForm1 = class(TForm)
Button1: TButton;
ComboBox1: TComboBox;
ColorBox1: TColorBox;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
ColorBox2: TColorBox;
//Image1: TImage;
Label4: TLabel;
ColorBox3: TColorBox;
ComboBox2: TComboBox;
Label5: TLabel;
Label6: TLabel;
Button2: TButton;
ListBox1: TListBox;
Label7: TLabel;
procedure Button1Click(Sender: TObject);
procedure ComboBox1Change(Sender: TObject);
procedure ColorBox1Change(Sender: TObject);
procedure ColorBox2Change(Sender: TObject);
procedure ColorBox3Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure Button2Click(Sender: TObject);
procedure ListBox1KeyPress(Sender: TObject; var Key: Char);
private
public
{ Public declarations }
end;
var
Form1: TForm1;
//Form2: TForm1;
Batar1: TBatar;
Batar2: TBatar;
//scale: integer; // масштаб
ColorFon: TColor; // цвет фона
MyMouse: TMouse;
i,j: byte; // счетчик Объектов Batar
ArrBatar: array[0..255] of TBatar;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
// и т. д. -
Cobalt © (20.06.12 11:59) [17]Учись отлаживать, использовать стек вызовов (Call Stack) и просмотр локальных переменных
Примечание:
в окошке "Local Variables" ты можешь "перейти" к списку локальных переменных по всему стеку вызовов вверх и обнаружить, когда была вызвана та или иная функция.
Понять, почему вызов той или иной функции в том или ином месте - неверное решение - это уже твоя задача -
Не пременно научусь, надо просто уже работу сдавать, а тут ошибка блин гребанная)if (X2party > Form2.Image1.Width) or (Y2body > Form2.Image1.Height) then
А не могли бы скинуть пример создания дочерней формы, сдается мне проблемма именно в этом, неправильно форму прикрутил и, следовательно, во внешний методах Form2.Image1.Width и не видно -
Омлет © (20.06.12 15:54) [19]> А не могли бы скинуть пример создания дочерней формы
http://not-doing.ru/some/form_sample.zip
1. Ссылка на вторую форму - это приватное поле главной формы. Если равна nil, то формы нет - в методах, где идет обращение ко второй форме, стоит сделать проверкуif MyForm2 <> nil then
begin
MyForm2.Image1.Canvas...
end;
2. Нет глобальной переменной для второй формы. Глобальные переменные - зло.
3. В dpr, естественно, вторая форма не создается при запуске, она создается динамически при нажатии на кнопке главной формы. -
> 3. В dpr, естественно, вторая форма не создается при запуске,
> она создается динамически при нажатии на кнопке главной
> формы.
Вот в этом и моя промашка была - разобрался в общем у меня получалось обращение к Form2.Image1.Width в процедуре TForm2.FormCreate (до момонта создания) поэтому Form2 = nil было, теперь заработало
Мастера Омлет и Cobalt спасибо, что направили на правильный путь -
Омлет © (20.06.12 16:14) [21]Блин, я совсем забыл, что тебе надо MDI.
По этой теме вагон статей есть. -
Омлет © (20.06.12 16:15) [22]> dan-1608 © (20.06.12 16:14) [20]
Вот правда, почитай какую-нибудь книгу. Гораздо легче будет. И MDI - это отдельная тема. -
Какую посоветуете лучше? так то кое-что было в закладках, но без практики теория мертва))
-
хотел реализовать, многопоточность воркспейсов, но теперь уже в следующей курсовой, много ньюансов
-
Омлет © (20.06.12 17:30) [25]
> dan-1608 © (20.06.12 16:27) [23]
> Какую посоветуете лучше?
Я по этой учился в своё время: http://rutracker.org/forum/viewtopic.php?t=2422037
Для D7 практически всё там актуально.