download help-editor .exe download help-editor Delphi-7 project Een eenvoudige editor voor In-Line help Aan programma's moet help informatie worden toegevoegd.Dat kan op drie manieren:
2. op een webpagina 3. als onderdeel van het programma De help informatie is opgeslagen in een stringlist component. Om de tekst samen te stellen is een eenvoudige editor geschreven. Toevoeging aan een applicatie geschiedt met een aparte (help) form en unit. De unit bevat alleen de delen van de editor om de tekst met besturingstekens weer te geven. Hieronder een iets verkleind plaatje van de editor: Standaard wordt tekst in het font “arial” afgebeeld met pixelhoogte 18. Andere stijlen zijn mogelijk met besturingsopdrachten in de tekst. Zo'n besturingsopdracht begint met een \ (backslash) teken, gevolgd door een letter. De mogelijkheden zijn
\c courier font \f vette tekst \l grote letters \i schuine tekst \t tab, horizontale uitlijning op veelvouden van 100 pixels \h koptekst \@naam; pijl met interne verwijzing \#naam; locatie aanduiding met naam De inhoud kan ook met de besturingsopdrachten en al worden weergegeven. Zo is te zien wat precies in ingetikt. Voor de afbeelding hier boven werd deze tekst ingevoerd: Opmerking 2: \n maakt voorgaande wijzigingen ongedaan De editor voorziet in 1000 lijnen tekst. Een regel is maximaal 120 tekens lang. De tekst kan worden gescrold. Invoegen van speciale tekens als č , ë gaat zo: Houd de alt toets ingedrukt en tik herhaald een “e” totdat de juiste e verschijnt. Om de regels te editen zijn er nog deze commando's : (CTRL = CONTROL toets)
CTRL Y verwijder de regel CTRL Z voeg een nieuwe regel in Het aardige van deze editor is, dat er eenvoudig uitbreidingen toegevoegd kunnen worden. Dat kan voor speciale programma's handig zijn. Het project Dat is geschreven in Delphi-7 en inmiddels is versie 6 bereikt.Form1/unit 1 bevat
afhandeling van toetsenbord en muis events procedure voor het weergeven van de tekstregels procedure voor het scrollen cursor besturing procedures voor het opslaan en openen van de tekst Helpform/helpunit bevatten een deel van de procedures van form1/unit1: voldoende om de tekst weer te geven en te scrollen. Deze helpform/helpunit kunnen aan een project worden toegevoegd voor In-Line help. Het programma const maxcolumn = 120; maxline = 1000; linesperpage = 31; lineheight = 25; maxtopline = maxline - linesperpage; standardfont = 'arial'; standardheight = 20; largeheight = 25; smallheight = 15; standardcolor = $000000; altcolor = $00a000; headercolor = $0000ff; standardbrush = $f0ffff; altbrush = $d8d8d8; standardstyles = []; topmarge = 5; leftmarge = 5; var textBuf : array[1..maxcolumn,1..maxline] of char; lineNr : smallInt; //line of cursor colNr : byte; //column of cursor topline : smallInt; //line at top of page bm : Tbitmap; realmode : boolean = true; cursrect : Trect; cursOn : boolean; scanmode : Tscanmode;De tekst staat in textbuf, elke regel wordt met #0 (character 0) afgesloten. Tekst wordt geschreven in de bitmap bm. De cursor alleen in de paintbox, dus die is altijd te wissen door een stukje (cursrect) van bm naar de paintbox te kopiëren. Topline is de regel die bovenaan in de paintbox staat. Bij het lezen van de tekst moet onderscheid worden gemaakt tussen besturingscodes en tekst. type TScanmode = (smRead,smControl,smSkip,smReal);betekenis:
smControl : na het \ character staat de edit code smSkip : skip de naam na een \@ of \# commando smReal : teken elk character, zodat de besturingscodes zichtbaar zijn function getcharwidth(c : char) : byte; //supply width of c begin result := trunc(bm.Canvas.textwidth(c)*1.1)+1; end; function getTextLength(nr : smallInt) : byte; //supply length of line, #0 ends string var i : byte; begin i := 1; while (i <= maxcolumn) and (textbuf[i,nr] <> #0) do inc(i); result := i-1; end; procedure paintline(nr : smallInt); //paint & update regel nr var i : byte; px,py : word; cc : char; dy : integer; begin dy := 5; px := leftmarge; py := (nr-topline)*lineheight+topmarge; linemode(0,px,py); //switch off bmNormal; //reset to default font if realmode then scanmode := smReal else scanmode := smRead; with bm.canvas do for i := 1 to getTextlength(nr) do begin cc := textBuf[i,nr]; case scanmode of smRead : if cc = controlchar then scanmode := smControl else begin textout(px,py+dy,cc); px := px + getcharwidth(cc); linemode(2,px,py); //kadertje tekenen end; smControl : begin scanmode := smRead; case upcase(cc) of 'C' : font.Name := 'courier new'; 'L' : begin font.height := largeheight; dy := 0; end; 'S' : begin font.height := smallheight; dy := 12; end; 'P' : begin font.height := smallheight; dy := 0; end; 'N' : begin font.name := standardfont; font.color := clBlack; font.height := standardheight; font.style := []; brush.color := standardbrush; font.Color := $0; dy := 5; linemode(0,px,py);//uitschakelen end; 'F' : font.style := font.Style + [fsbold]; 'M' : begin brush.Style := bsSolid; brush.color := altbrush; end; 'T' : px := ((px div 100)+1)*100; '[' : linemode(1,px,py); //init 'I' : begin font.Style := font.Style + [fsItalic]; font.color := clBlue; end; 'H' : begin font.Color := $0000a0; font.Height := 25; dy := 0; end; '@' : begin draw(px,py,arrow); inc(px,arrow.width); scanmode := smSkip; end; '#' : begin draw(px,py,dot); inc(px,dot.width); scanmode := smSkip; end; end;//case end; smSkip : case cc of ';', ' ' : scanmode := smRead; controlchar : scanmode := smControl; end; smReal : begin textout(px,py+dy,cc); px := px + getcharwidth(cc); end; end;//case end;//for end;Zoals is te zien kunnen eenvoudig extra besturingscodes worden toegevoegd. De lijn staat nu in de bitmap en moet in de paintbox worden getoond. Daarvoor zorgen: function getLineRect : Trect; var nr : smallInt; begin nr := lineNr - topline; with result do begin Left := 0; Right := bm.Width; Top := nr * lineheight + topmarge; Bottom := Top + lineheight; end; end; procedure eraseLine; var r : Trect; begin r := getLineRect; with bm do with canvas do begin brush.color := standardbrush; brush.Style := bsSolid; fillrect(r); end; end; procedure showline; var r : Trect; begin r := getLineRect; form1.helpbox.canvas.copyrect(r,bm.Canvas,r); end; procedure refreshline; begin cursOn := false; eraseline; paintline(lineNr); showline; cursorOn; end; Interne links Help informatie zal meestal beginnen met een inhoudsopgave.Het is handig om vanuit die inhoudsopgave direct naar een onderwerp te kunnen springen. Daarvoor dient de opdracht \@piet; die een pijltje neerzet: “piet” is de naam van de regel die bovenaan in de paintbox komt te staan als op het pijltje wordt geklikt. Bij de bovenstaande opdracht hoort: \#piet; wat een rondje oplevert: Om effectief te zijn, moet de naam “piet” in de linklist staan. Indrukken van de menuknop LINK maakt deze lijst. Const maxlink = 50; type TLinklist = record s : string; px1 : smallInt; //x position px2 : smallInt; L1 : smallInt; //first line L2 : smallInt; //second line end; var linklist : array[1..maxlink] of TLinklist; linkcount : byte;s is de naam. Px1..px2 zijn de horizontale pixel posities (links, rechts) op de regel. L1 is de lijn waarop het pijltje staat, dus de \@ opdracht. L2 is de lijn waarop het rondje staat, de \# opdracht. procedure makelinklist; var i,n,k : byte; j : smallInt; cc : char; m : Tscanmode; orgF : boolean; id : string; OK : boolean; begin orgF := false; n := 0; for j := 1 to maxline do begin m := smRead; for i := 1 to gettextlength(j) do begin cc := textbuf[i,j]; case m of smRead : if cc = controlchar then m := smControl; smControl : case cc of '@' : begin m := smSkip; orgF := true; id := ''; end; '#' : begin m := smSkip; orgF := false; id := ''; end; else m := smRead; end; smSkip : case cc of controlchar : m := smRead; ';' : begin m := smRead; if (n < maxlink) and (length(id) > 0) then if orgF then begin inc(n); linklist[n].s := id; linklist[n].L1 := j; linklist[n].px1 := getCursorPos(i,j)-arrow.width; end else if linkpos(k,id) then begin linklist[k].L2 := j; linklist[k].px2 := getcursorpos(i,j)-dot.Width; end; end; else id := id + cc; end; //case cc of end;//case end;//i end;//j with form1.msgtext do if n = 0 then caption := 'no links found' else caption := 'links found = '+ inttostr(n); linkcount := n; OK := linkcount > 0; i := 0; while OK and (i < linkcount) do begin inc(i); with linklist[i] do begin if L1 = L2 then begin OK := false; form1.msgtext.caption := 'line '+ inttostr(L1)+ ' points to itself'; end; if L2 = 0 then begin OK := false; form1.msgtext.caption := 'line '+ inttostr(L1)+ ' points to nothing'; end; end; end;//while OK := linkcount > 1; i := 0; while OK and (i < linkcount-1) do begin inc(i); k := i; while OK and (k < linkcount) do begin inc(k); OK := linklist[i].s <> linklist[k].s; if OK = false then form1.msgtext.Caption := 'duplicate link names'; end; end; end;De hele tekst wordt doorlopen waarbij gezocht wordt naar \@ en \# commando's. Gecontroleerd word of de pijltjes en rondjes matchen. De functie getcursorpos levert de positie van de cursor. Zie de source code. Bewaren van Help bestanden De help informatie wordt opgeslagen als text bestand.procedure Tform1.saveBtnClick(Sender: TObject); var w : word; size : word; outfile : textfile; s : string; OK : boolean; begin //bepaal de lengte van de tekst size := 0; OK := false; for w := 1 to maxline do if gettextlength(w) > 0 then size := w; if size = 0 then exit; with form1.SaveDialog1 do if execute then try assignfile(outfile,filename); rewrite(outfile); for w := 1 to size do begin s := buf2string(w); writeln(outfile,s); end; OK := true; finally closefile(outfile); If OK then msgtext.Caption := 'file saved. Lines = '+inttostr(size) else msgtext.Caption := 'cannot write file'; end; end;Voor verdere details verwijs ik naar de source code. De Help Editor is heel simpel, maar heeft zijn nut reeds bewezen. Een toepassing van de helptekst is te vinden in het grafiek programma graphics-explorer zie HIER . |
||||||