Конференция "KOL" » Вопросы к Старшим [D7, WinXP]
 
  • MYRX (17.04.08 10:56) [0]
    Добрый день, уважаемые мастера. Взялся я писать куросовой на 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 на фрейме

    вопрос заключается в следующем:
    как мою задумку организовать правильно

    а еще как все это правильно уничтожить при закрытии вкладки
    подскажите плиззз
  • Danger © (17.04.08 12:59) [1]
    Можно оформить это все в отдельный объект (скажем, 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() и. т.п. В общем, в такой схеме можно всегда обратиться к любому контролу на любой вкладке, и упростить работу с блоком контролов на вкладке, управлять созданием/уничтожением целых блоков контролов при необходимости.
  • Danger © (17.04.08 13:05) [2]
    А в качестве memo, кроме обычного memo, можно использовать RichEdit; KOLHilightMemo Владимира Кладова; или VMHSyntaxEdit, VMHPasHighlighter (последние, впрочем, глючат неслабо).
  • MYRX (17.04.08 13:41) [3]
    Спасибо, Danger, направление мысли понял. Если не трудно приведи примерчик для тех, кто в танке. Признаюсь честно: я - в бронепоезде
  • Дмитрий К © (17.04.08 13:58) [4]
    А можно, например, так: один memo и панелька с кнопочками.  К каждой кнопочке привязан объект в котором хранятся путь файла, изменения в файле, еще какая-нибудь лабуда. При создании кнопочки объект создается, инициализируются его поля. При разрушении соответственно все уничтожается.
    Для кнопочек можно использовать тот же TabControl, только его "кнопочную" часть, скрыв под memo все остальное.
  • MYRX (17.04.08 14:15) [5]
    Спасибо за совет, Дмитрий.
    Все-таки я предпочту "Вкладочный" вариант.
    Только есть одна просьбочка ко всем мастерам.
    Я не представляю, как динамически создавать объект, состоящий из кучи других объектов, да еще как-то это все закинуть на вкладку, может кто-нить поделится, хоть приблизительным описанием подобного объекта на языке Паскаль и кодом его инициализации и уничтожения?
  • Danger © (17.04.08 15:16) [6]

    > MYRX   (17.04.08 13:41) [3]
    > Если не трудно, приведи примерчик для тех, кто в танке.
    > Признаюсь честно: я - в бронепоезде

    Попозже кину пример создания объекта, в данный момент немного занят ...


    > Я не представляю, как динамически создавать объект, состоящий
    > из кучи других объектов, да еще как-то это все закинуть
    > на вкладку, может кто-нить поделится, хоть приблизительным
    > описанием подобного объекта на языке Паскаль и кодом его
    > инициализации и уничтожения?

    Точно так же, как динамически создается любой другой объект (форму, кнопку и т.п.).
  • Barloggg (17.04.08 15:36) [7]
    > MYRX   (17.04.08 13:41) [3]
    покури пример с Frame

    создаешь два проекта. или лучше просто две формы
    первый твой таб с вкладками и делается как обычно
    второй это конкретно одна вкладка со всем что тебе на ней нужно. только вместо КолФорм надо бросить туда КолФраме.

    убрать вторую форму из списка автосоздаваемых.
    а потом нужное тебе количество вкладок клонировать как сказал Danger [1]
  • MYRX (17.04.08 19:35) [8]
    Спасибо всем за содействие
    2 Danger если на форум влом скидывать пример, то скинь, пожалуйста на
    myrx@inbox.ru
  • Danger © (18.04.08 10:28) [9]

    > MYRX   (17.04.08 19:35) [8]

    Вот простой пример набросал: http://alhoster.com/TabEditExample.7z
    Буду рад, если поможет.
  • MYRX (18.04.08 15:55) [10]
    Спасибо огоромное!

    пример вывел меня из тупика
    теперь могу писать курсовой дальше
  • MYRX (18.04.08 16:07) [11]
    Появился еще один вопрос к мастерам

    хочется сделать красивый About, на основе картинки jpg
    но вот незадача, как в программу "запихнуть" эту картинку

    логично использовать ресурсы

    Сложность-же заключается в том, как из этих ресурсов
    взять эту картинку, декодировать и нарисовать на канвасе
    формы, не создавая промежуточного файла.

    Снова надеюсь старших товарищей
    Может кто-нить подкинет кода кусочек?
  • Compiler © (18.04.08 22:16) [12]
    Для работы с 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;

  • MYRX (19.04.08 01:57) [13]
    Быстро, посто и удобно!
    Все работает
    Спасибо, Compiler!
  • MYRX (21.04.08 02:41) [14]
    Снова я)
    Запостю весь топик глупыми вопросами,
    но что делать?

    Если нет своего ума - одолжи у другого.

    Возник вопрос такой:
    хочу в этом редакторе подсветку синтаксиса сделать на базе 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
    программа увеличилась вдвое ((
  • Danger © (21.04.08 11:07) [15]

    > P.S.
    > Пробовал использовать PVMHSyntaxEdit + PVMHPasHighlighter
    > программа увеличилась вдвое ((

    Ладно бы размер, но к сожалению там есть глюки в самом редакторе - к примеру, помню, что не удавалось перетащить выделенный блок текста в редакторе (хотя оригинальный TSynEdit позволял так делать).
  • mdw © (21.04.08 11:41) [16]
    У меня примерно так. Правда многострочные коментарии так и не доделал.

    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;
  • MYRX (21.04.08 17:06) [17]
    Спасибо, mdw!
    сегодня ночью попробую.

    Вот только не понимая что к чему трудно пользоваться, а тем более дорабатывать

    Я так и не могу понять:
    1) что мы должны вернуть в резалте HEditScanToken,
       т.е. что означает возвращаемое нами число?

    2)Что вообще означает "Токен"? (просто если пойму, то наверное будет попроще)
  • mdw © (21.04.08 19:11) [18]

    > 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 будет вызываться уже со сдвигом на эту длину.
  • MYRX (21.04.08 20:05) [19]
    Спасибо.
    Теперь все встало на свои места.
 
Конференция "KOL" » Вопросы к Старшим [D7, WinXP]
Есть новые Нет новых   [134431   +14][b:0][p:0.003]