-
Добрый день, уважаемые мастера. Взялся я писать куросовой на KOL хочется написать простенький редактор pas-файлов Задумка: возможность открывать несколько файлов на разных вкладках для этого сделал отдельный фрейм с редактром кода и создаю его на каждой вкладке так:
procedure CreateEmptyTab(Str:String);
var tmp:PfrEditor;
begin
if not Assigned(FrameList) then
FrameList:=NewList;
if not Assigned(PathList) then
PathList:=NewStrList;
fmMan.TCMain.TC_Insert(fmMan.TCMain.Count,'',0);
fmMan.TCMain.CurIndex:=fmMan.TCMain.Count-1;
fmMan.TCMain.TC_Items[fmMan.TCMain.CurIndex]:=Str;
NewfrEditor(tmp,fmMan.TCMain.Pages[fmMan.TCMain.CurIndex]);
FrameList.Add(tmp);
PfrEditor(FrameList.Item[fmMan.TCMain.CurIndex]).MEPas.Focused:=True;
PathList.Add('');
end;
В PathList храню пути до файлов, открытых на вкладках или пустую строку, если вкладка пустая в FrameList хранятся указатели на созданные фреймы MEPas - это memo на фрейме вопрос заключается в следующем: как мою задумку организовать правильноа еще как все это правильно уничтожить при закрытии вкладки подскажите плиззз
-
Можно оформить это все в отдельный объект (скажем, TEditor), членами которого являются memo и прочие контролы на вкладке. Указатели на экземпляры TEditor хранить в глобальном динамическом массиве: TEditors = array of TEditor; При создании вкладки динамически создаем объект (в конструкторе объекта будет инициализироваться memo и прочие контролы), и добавляем указатель на объект TEditor в массив, для последующих обращений к объекту и его дочерним объектам (memo, например). При закрытии вклядки уничтожать объект TEditor и его дочерние объеты. Удаляем из массива указатель на объект (если надо, сдвигаем элементы к началу массива и устанавливаем новую длину массива). Обращаться к memo, расположенным на разных вкладках легко, т.к. номер вкладки будет совпадать с индексом экземпляра TEditor в массиве. Т.е., чтобы обратиться к свойству Text у memo, расположенному на третьей вкладке, делаем примерно TEditors[2].Memo.Text:= 'blablabla'; Дополнительно, для удобства можно ввести в объект TEditor методы, например TEditor.LoadFile(), TEditor.SaveFile(), TEditor.CopyToInternalClipboard() и. т.п. В общем, в такой схеме можно всегда обратиться к любому контролу на любой вкладке, и упростить работу с блоком контролов на вкладке, управлять созданием/уничтожением целых блоков контролов при необходимости.
-
А в качестве memo, кроме обычного memo, можно использовать RichEdit; KOLHilightMemo Владимира Кладова; или VMHSyntaxEdit, VMHPasHighlighter (последние, впрочем, глючат неслабо).
-
Спасибо, Danger, направление мысли понял. Если не трудно приведи примерчик для тех, кто в танке. Признаюсь честно: я - в бронепоезде
-
А можно, например, так: один memo и панелька с кнопочками. К каждой кнопочке привязан объект в котором хранятся путь файла, изменения в файле, еще какая-нибудь лабуда. При создании кнопочки объект создается, инициализируются его поля. При разрушении соответственно все уничтожается. Для кнопочек можно использовать тот же TabControl, только его "кнопочную" часть, скрыв под memo все остальное.
-
Спасибо за совет, Дмитрий. Все-таки я предпочту "Вкладочный" вариант. Только есть одна просьбочка ко всем мастерам. Я не представляю, как динамически создавать объект, состоящий из кучи других объектов, да еще как-то это все закинуть на вкладку, может кто-нить поделится, хоть приблизительным описанием подобного объекта на языке Паскаль и кодом его инициализации и уничтожения?
-
> MYRX (17.04.08 13:41) [3] > Если не трудно, приведи примерчик для тех, кто в танке. > Признаюсь честно: я - в бронепоезде
Попозже кину пример создания объекта, в данный момент немного занят ...
> Я не представляю, как динамически создавать объект, состоящий > из кучи других объектов, да еще как-то это все закинуть > на вкладку, может кто-нить поделится, хоть приблизительным > описанием подобного объекта на языке Паскаль и кодом его > инициализации и уничтожения?
Точно так же, как динамически создается любой другой объект (форму, кнопку и т.п.).
-
> MYRX (17.04.08 13:41) [3] покури пример с Frame
создаешь два проекта. или лучше просто две формы первый твой таб с вкладками и делается как обычно второй это конкретно одна вкладка со всем что тебе на ней нужно. только вместо КолФорм надо бросить туда КолФраме.
убрать вторую форму из списка автосоздаваемых. а потом нужное тебе количество вкладок клонировать как сказал Danger [1]
-
Спасибо всем за содействие 2 Danger если на форум влом скидывать пример, то скинь, пожалуйста на myrx@inbox.ru
-
-
Спасибо огоромное!
пример вывел меня из тупика теперь могу писать курсовой дальше
-
Появился еще один вопрос к мастерам
хочется сделать красивый About, на основе картинки jpg но вот незадача, как в программу "запихнуть" эту картинку
логично использовать ресурсы
Сложность-же заключается в том, как из этих ресурсов взять эту картинку, декодировать и нарисовать на канвасе формы, не создавая промежуточного файла.
Снова надеюсь старших товарищей Может кто-нить подкинет кода кусочек?
-
Для работы с jpeg и gif я использую юнит tinyJPGGIFBM от homm, который входит в состав GrushControls Вот примерчик:
var
B:PBitmap;
...
b:=NewBitmap(0,0);
tinyLoadJPGGIFBMPResource(b,hinstance,'Splash','Splash');
b.Draw(Form.canvas.handle,0,0);
...
B.Free;
-
Быстро, посто и удобно! Все работает Спасибо, Compiler!
-
Снова я) Запостю весь топик глупыми вопросами, но что делать? Если нет своего ума - одолжи у другого. Возник вопрос такой: хочу в этом редакторе подсветку синтаксиса сделать на базе KOLHilightEdit очень шустрый, маленький и функциональный компонент, (респект Кладову) но вот беда, не получается у меня пользоваться его функционалом ключевые слова кое-как подсвечиваю
function TEditor.HilightPAS(Sender: PControl; const FromPos: TPoint; var Attrs: TTokenAttrs): Integer;
...
begin
S := fHEdit.Edit.Lines[ FromPos.Y ];
Result := 0;
if S = '' then
begin
i := FromPos.X;
isReserved := FALSE;
...
if not fStr and
((AnsiCompareStrNoCase( Copy( S, i+1, 5 ), 'begin' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 3 ), 'end' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 3 ), 'var' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 5 ), 'const' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 2 ), 'or' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 2 ), 'if' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 4 ), 'then' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 3 ), 'for' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 5 ), 'while' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 2 ), 'do' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 8 ), 'function' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 9 ), 'procedure' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 14 ), 'implementation' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 5 ), 'array' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 11 ), 'constructor' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 8 ), 'property' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 4 ), 'type' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 10 ), 'destructor' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 4 ), 'uses' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 9 ), 'interface' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 7 ), 'program' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 2 ), 'in' ) = 0) or
(AnsiCompareStrNoCase( Copy( S, i+1, 4 ), 'object' ) = 0)
... ) then
begin
isReserved := TRUE;
if S[ i+1 ] <= ' ' then
while (i < Length( S )) and (S[ i+1 ] <= ' ') and ( not (S[ i+1 ] in delims)) and (S[i+1]<>#39) do inc( i )
else
while (i < Length( S )) and (S[ i+1 ] > ' ') and ( not (S[ i+1 ] in delims)) and (S[i+1]<>#39) do inc( i );
end
...
Result := i - FromPos.x;
if isReserved then
begin
Attrs.fontstyle := [ fsBold ];
Attrs.fontcolor := 16776960;
Attrs.backcolor := clBlack;
end
...
begin
Attrs.FontStyle := [ ];
Attrs.fontcolor := clWhite;
Attrs.backcolor := clBlack;
end;
end;
А вот как подсветить строковые параметры (те, что в кавычках)? - ума не приложу до 3-х часов ночи бился, так и не победил поделитесь, кто-нить опытом, если не жалко... P.S. Пробовал использовать PVMHSyntaxEdit + PVMHPasHighlighter программа увеличилась вдвое ((
-
> P.S. > Пробовал использовать PVMHSyntaxEdit + PVMHPasHighlighter > программа увеличилась вдвое ((
Ладно бы размер, но к сожалению там есть глюки в самом редакторе - к примеру, помню, что не удавалось перетащить выделенный блок текста в редакторе (хотя оригинальный TSynEdit позволял так делать).
-
У меня примерно так. Правда многострочные коментарии так и не доделал.
type TTokens = (tNone, tReservedWord, tComment, tCharStr, tDigital); const ReservedWordsCount = 72; ReservedWords: array [0..ReservedWordsCount-1]of string = ( 'and', 'array', 'as', 'asm', 'begin', 'case', 'class', 'const', 'constructor', 'destructor', 'dispinterface', 'div', 'do', 'downto', 'else', 'end', 'except', 'exports', 'file', 'finalization', 'finally', 'for', 'function', 'goto', 'if', 'implementation', 'in', 'inherited', 'initialization', 'inline', 'interface', 'is', 'label', 'library', 'mod', 'nil', 'not', 'object', 'of', 'or', 'out', 'packed', 'procedure', 'program', 'property', 'raise', 'record', 'repeat', 'resourcestring', 'set', 'shl', 'shr', 'string', 'then', 'threadvar', 'to', 'try', 'type', 'unit', 'until', 'uses', 'var', 'while', 'with', 'xor', 'private', 'protected', 'public', 'published', 'automated', 'at', 'on' );
procedure TCodesForm.KOLMDIChildFormCreate(Sender: PObj); var i: Integer; Item: THandle; begin FReservedWords:= NewStrList; for i:= 0 to ReservedWordsCount-1 do ReservedWords.Add(ReservedWords[i]); FReservedWords.Sort(False); end;
function TCodesForm.HEditScanToken(Sender: PControl; const FromPos: TPoint; var Attrs: TTokenAttrs): Integer; begin Attrs.fontcolor := clWindowText; Attrs.fontstyle := [ ]; case ParseLine(HEdit.Edit.Lines[FromPos.Y], FromPos.X+1, Result) of tReservedWord: Attrs.fontstyle:= [fsBold]; tComment: begin Attrs.fontstyle:= [fsItalic]; Attrs.fontcolor:= clGrayText; end; tCharStr: begin Attrs.fontstyle:= []; Attrs.fontcolor:= clFuchsia; end; tDigital: begin Attrs.fontstyle:= []; Attrs.fontcolor:= clBlue; end; end end;
const Separators = ' ;.,:=><()[]*+-/@^${}';
// {} (* *) function TCodesForm.ParseLine(ASource: String; APos: Integer; var ALength: Integer): TTokens; var k: Integer; S: String; begin Result:= tNone; ALength:= 1; ASource:= AnsiLowerCase(ASource); Delete(ASource, 1, APos-1); if ASource = '' then Exit;
//Коментарии if Copy(ASource, 1, 2) = '//' then begin ALength:= Length(ASource); Result:= tComment; Exit; end; if (ASource[1] = '{') then begin ALength:= Pos('}', ASource); if ALength = 0 then ALength:= Length(ASource); Result:= tComment; Exit; end;
//Строки if ASource[1] = '''' then begin Delete(ASource, 1, 1); k:= Pos('''', ASource); if k = 0 then k:= Length(ASource); ALength:= k+1; Result:= tCharStr; Exit; end; if ASource[1] = '#' then begin ALength:= 1; while (Length(ASource)>ALength)and(ASource[ALength+1] in ['#', '0'..'9']) do inc(ALength); Result:= tCharStr; Exit; end;
//Цифры if ASource[1] in ['$', '0'..'9'] then begin ALength:= 1; while (Length(ASource)>ALength)and ((ASource[ALength+1] in ['.', '0'..'9'])or ((ASource[1]='$')and(ASource[ALength+1] in ['a'..'f']))) do inc(ALength); Result:= tDigital; Exit; end;
S:= Parse(ASource, Separators); if FReservedWords.Find(S, k) then Result:= tReservedWord; ALength:= Max(1, Length(S)); end;
-
Спасибо, mdw! сегодня ночью попробую.
Вот только не понимая что к чему трудно пользоваться, а тем более дорабатывать
Я так и не могу понять: 1) что мы должны вернуть в резалте HEditScanToken, т.е. что означает возвращаемое нами число?
2)Что вообще означает "Токен"? (просто если пойму, то наверное будет попроще)
-
> 2)Что вообще означает "Токен"? (просто если пойму, то наверное > будет попроще)
token 1) знак 2) примета, признак
> 1) что мы должны вернуть в резалте HEditScanToken, т. > е. что означает возвращаемое нами число?
Открываем KOLHilightEdit.pas и читаем:
TOnScanToken = function( Sender: PControl; const FromPos: TPoint; var Attrs: TTokenAttrs ): Integer of object; { Методика подцветки синтаксиса такова: устанавливается обработчик события OnScanToken, который по необходимости получает координату FromPos, берет строку Lines[ FromPos.Y ], и с позиции FromPos.X (считается с нуля) определяет атрибуты токена (записывает их в Attrs), и возвращает длину токена. Не надо делать никакого компонента, если без него можно обойтись. }
Короче, вернуть должны длину строки, для которой устанавливаем атрибуты Attrs, в следующий раз OnScanToken будет вызываться уже со сдвигом на эту длину.
-
Спасибо. Теперь все встало на свои места.
|