DELPHI4ProgrammingManual ¦ Jan2022 UNIVERSUMS HISTORIA | 2011V4 ¦ 2022I18 | aproduction | Senast uppdaterade version: 2022-09-10 YMD ¦  HumanRight is a knowledge domain  

 

content · webbSÖK äMNESORD på denna sida Ctrl+F   SubjectINDEX      all files    helpStart

 

 

 

Elementär FlytbildsTeknik flytbildsläget16;64-felet i DELPHI4 | EditColors | TabellHIMRV |  Se även BILDHANTERING [PictureHANDLING/picture manipulation] allmänt

 

GENERAL IMAGE HANDLING IN Delphi4Test2022 ¦ ImportExport

Foto:  15Sep2014  E32  Bild112  · NikonD90 ¦ NaturenRef

 

 

Hur flytbildsläget fungerar med ovanstående illustrations begrepp beskrivs också utförligt i

FLYTBILDSFLAGGOR.

Exempel, 4Sep2014

I tur och ordning — detta htm-dokument:

DelphiBegin ¦ DelphiKOD ¦ ProgramFÖNSTRET ¦ KOMPONENTER ¦ ProjektKatalogen ¦ ExeIcon ¦ Label1 ¦ ProgramENHETER ¦ Caption — FönsterNamn ¦ BildKODteknik ¦ Alla 4 Procedurer ¦ Peken ¦ Ctrl+V ¦ Resultat1 ¦ FlytBildsTEKNIK ¦ F5 ¦

BildEXPORT — Ctrl+I | PilotDISPLAY | MARKÖRACCELERATORER | Resultat2 | Flytbilden | RitaMusHÖGER | MoveMore | MultiWin ¦ Flytsätten ¦ BGOF ¦ INVERTERA ¦ RGB palett ¦ FEL1664 ¦ TBitMapInfoHeader ¦ EditColors ¦

Unit1A ¦ StreckRektangeln ¦ ClipCursor ¦ PROGRAMDIVERGENS ¦ HELPex ¦ HIMRV | Zoom | WriteText | TextIn | RamToning | CommanderDoit | Label1 | Label1 | Label1 | Label1 ¦

http://www.universumshistoria.se/AAALib/DELPHI4/HTM/AD4a1Begin.htm

29OKT2014

Behandlat | P2:

FlytBildsFunktionerna MoveAND|Copy|SkipWHITE — Flytsätten

RitaMusHöger — motsvarar »pennan i bröstfickan»: alltid tillgänglig på bildytan

BildHantering: Invertera|Rotera90°|VändHorisontellt¦Vertikalt|Duplicera|Radera|Kopiera — TabellHIMRV

RGB|HSBRGB-palett med

EditColors — färgredigering och analys

Zoomning

WriteText — snabb, effektiv text på bild

TextIn — TrueType-text mot godtyckliga bakgrunder

RamToning — sammansmältning med flera bilder

CommanderDoit — ritaVerktyg

 

 

Elementära datorhjälpmedel — flytta kombinera sammanställa bilddetaljer UTAN NÅGON DIREKT BILDBEHANDLINGSTEKNIK

Uppbyggnad av ett flytbildsblock i Delphi4

Hel programform i detalj — exakt pixelpositionering — se tabellen med alla flytbildskommandon i TabellHIMRV

Arkivet 2011 ¦ 14:

 

Vidareutvecklat Från DELPHI 4 Test 2011 — BellDHARMA  for UniverseHistory — HUVUDDELEN AV VERKTYGEN MAN BEHÖVER FÖR AVANCERAD DATORANVÄNDNING I TEXT OCH BILD

 

      Delphi4 Programming Manual 2014|a1

   — elementär flytbildsteknik

AllmänDistribution DELPHI4 MANUAL BellDHARMA Sep2014 — T2014

 

DISPOSITION T2014 |  TeckenförklaringarAllmänt: MusKLICKVänster | Höger:  |   — RullaMushjulet FRÅN | MOTDig:  |

 

 

Uppbyggnad — flytbildsblock:

1. Image1: synlig bildytan (»titten») vi alltid tittar på på bildskärmen;

2. Image2: gömd flytbilden = urklippskopian vi tar in och som ska flyttas — flyta — omkring på, i, över, genom titten;

3. Image3: gömd KOPIATORN som räddar undan en tittkopia INNAN Flyten läggs på:

 

 Nedan beskrivs detaljerna hur man kan förverkliga verktygen: Panel1 med Image1, Image2 och Image3

 

— För varje ny position lägger Im3 FÖRST tillbaka föregående uttag på TittOriginalets plats; SEDAN tar Im3 in en ny kopia av Tittstället där Flyten kommer att läggas på i nästa snäpp — totalt med TYP Ctrl+Pilar (eller konventionell musflyttning [jag använder själv aldrig musen för bildflyttning i mina program; Ctrl+ NumPad 1 2 3 5 9 sätter flyttsteg om 1 5 20 Halvsida Helsida pixels: helt underbar funktion: snabbt, exakt]) att den intagna urklippskopian FLYTER obehindrat över Titten utan att ändra något.

 

Efter min erfarenhet:

1. Lägg ALDRIG en SYNLIG ImageKomponent i DELPHI(4) direkt på en formyta = själva programfönsterkomponenten. Gör man det upptäcker man snart ett hedjlöst FLIMRANDE vid fönsterändringar;

2. Reservera ALLTID en PanelKomponent som bas till en SYNLIG ImageKomponent för att få störningsfria övergångar i alla möjliga sammanhang: Panel1 med Image1 osv.

3. Principen är densamma för Labels (textRemseKomponenter) på Image: sporadiska mindre flimmer uppkommer om LabelKomponenten genomgår upprepade ändringar.

— Det gäller även till viss del Labels på Panels — ett fenomen i DELPHI(4) man får försöka kämpa med och hitta lösningar till om det börjar jävlas särskilt. Generellt sett är dock det inget problem.

— Det generella sättet att HELT eliminera flimmertyper mellan olika pålagda komponenter är helt enkelt att skippa dem och att skriva KOD PÅ Image direkt: I Delphi(4) finns (nämligen) ingenting man INTE kan göra med en bild: text, grafik, foto, rit. Men dessa är bara mina egna erfarenheten. Testa själv är bäst.

 

DelphiBegin:

Här: DELPHI1 från Start (gavs ut som gratisprogram från 1997):

 

Objekt:

 

 

 

— DELPHI4 ser ut ungefär på samma sätt, bara med skillnaden att det finns något fler komponenter samt att hela systemet stödjer 32-bitars databusstruktur mot endast 16 bitar i Delphi1.

— Komponenter dras från Raddan med tabbade komponentlister till Form1 — programfönstrets bildyta — och förses med separat KOD i Edit-fönstret som här ligger bakom Form1 (Man växlar mellan dessa Med F12 och till ObjectInspector med F11).

— Form1-fönstret är samma som (det kommande) programfönstret, och man fyller formen med komponenter: Knappar, Paneler Bildytor (Image), Textboxar, Memoboxar, Listboxar, osv. — eller att man kan skriva KOD för alla dessa.

— Bakom Form1-fönstret [F12] ligger den avgörande centrala CodeEdit-fönstret (Unit1, Unit2, Unit ...); Programkod skrivs där i Borland Turbo Pascal (Kodsidorna eller Units sparas sedan i Projektkatalogen som *.pas-filer = vanliga textfiler med specialfiländelse: sedan DELPHI4 kompilerat [Ctrl+F9] dessa till en fungerande exe-fil, är dessa kodsidor bara »rester» — som kan byggas på, vidare med nya kompileringar [Ctrl+9] osv.).

— Se även i INSTALLATIONSANVISNINGAR med StartExempel hur allt ser ut från början i DELPHI4, och hur man kan göra grundinställningar som garanterar en maximalt smidig funktion från början.

 

DelphiKod:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Så här ser KodFönstret ut i DELPHI4 då ett helt nytt projekt påbörjats (Alt+File), New Application:

 

 

KodFönstren i DELPHI4 finns förtecknade i ViewUnit och anropas med Ctrl+F12,

 

 

Projekten i DELPHI4 — obs: öppnas på SENAST ÖPPNADE — finns förtecknade i OpenProject med Ctrl+F11,

 

 

ProjektFilen man ska leta efter ock klicka på har filändelsen dpr med DELPHI4-logon som den gula AntikPortalen:

 

 

INGENTING AV DESSA BERÖR DOCK NYBÖRJARENS FÖRSTA BEKANTSKAP. Ovanstående kommer senare, vid behov.

 

— SEDAN man initierat flera olika projekt, finns ett alternativt sätt att växla mellan flera olika projekt — bara ett projekt åt gången får vara öppet i DELPHI4:

— Tryck Alt+F+R(eopen); DELPHI4 visar en lista med de senast öppnade projekten, och det är bara att välja direkt därifrån.

 

 

Programfönstret:

— Ingen kod finns ännu inskriven. Men snart.

— Jag har här försökt trycka på F9 = KÖR för att tvinga DELPHI4 att spara upp det nya projektet på (en av mig anvisad) plats (Katalog P2) och ett nytt projektnamn (P2): DELPHI4 visar automatiskt dialogrutor för detta (fyll i och fortsätt — efter denna första initiering sköter sedan DELPHI4 automatiskt uppdateringar på den anvisade platsen för varje ny körning;

Se mina exempel på grundinställningar i INSTALLATIONSANVISNINGAR, AutoSaveOptions).

Jag har här (Object Inspector, tangent F11) satt Form1-programfönstrets mått XY till 200;500pixel:

 

 

Komponenter:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Nu börjar vi med att lägga in en Panel1, en Image1, Image2, och en Image3:

— vi klickar på komponenterna på Tabbflikarna,

 

 

släpper komponenterna på Form1-ytan, och DELPHI4 skriver automatiskt in Grunddata åt oss;

Ctrl+Pilar flyttar komponenterna 1 pixel på formytan och Ctrl+Shift+Pilar flyttar 8pixels.

Shift+PilUppNer reglerar höjd och Shift+PilVäHö reglerar längd. Dessa kan också skrivas in med värden direkt i Object Inspector.

— Notera också Anchors på ObjectInspector: Dubbelklicka på Achorsrutan och ställ in önskat. Standard är att varje komponent VID FÖNSTERÄNDRINGAR ligger LÅST TopLeft. Men vi kan ändra dessa så att t.ex. en bottenpanel alltid fortsätter ligga LeftBottom med fönsterändringar.

— Om vi redan har en viss komponent på formytan och vill ha flera av den typen, går det också att köra Ctrl+C, sätta fokus på formytan (annars blir den valda komponenten Parent) och ta in en redan formaterat (Object Inspector) komponent med samma mått och egenskaper:

 

 

Avgörande viktigt för att bildintagen ska fungera korrekt är att vi på Object Inspector (F11) för Image2 och Image3 sätter egenskapen AutoSize=True men False på Image1. För att säkra grundinställningarna kan vi skriva in dem i kod på FormCreate — nedan också med en mindre aggressivt orange bakgrundsfärg till Label1 (beskrivs längre fram), samt en alternativ teckensnittsfärg (mörkviolett) för att exemplifiera personliga val:

 

       Left:= (Screen.Width -  Width)  div 2;

       Top:=  (Screen.Height - Height) div 2;

       Image1.AutoSize:= False;

       Image2.AutoSize:= True;

       Image3.AutoSize:= True;

       Label1.Color:= RGB(255,238,221);

       Label1.Font.Color:= clPurple;

 

De bägge översta raderna garanterar att ProgramFönstret alltid öppnas mitt på bildskärmen.

 

 

Vad är ”clPurple”? Placera markören i DELPHI4:s kodfönster i ordet och tryck F1: en  separat hjälpruta kommer fram från den omfattande hjälpen och beskriver detaljerna. Grundfärger har namn (clBlack, clWhite, clBlue, clNavy, clPuple, ...), medan färger generellt kan anges i RGB eller Hexkod.

 

Panel1 som Parent till Image1, och två ytterligare Image separat (som kommer att fungera gömda) Image2 och Image3.

Notera egenskaperna Visible med True och False på komponenterna i Object Inspector: Panel1 och Image1 ska vara Visible=Synliga hela tiden, medan Image2 och 3 ska vara Visible=False; Ctrl+Enter ändrar True/False direkt med vald komponent och Visible i Object Inspector;

 

För att markera gemensamma egenskaper för flera komponenter åt gången: Klicka på/markera första komponenten; håll

1. ner Shift och klicka på alla övriga som önskas;

eller

2. MusVäNer och dra streckrektangeln över alla;

Gå sedan till Object Inspector och sätt önskad egenskap.

 

Med de ovan införda ändringarna, trycker jag nu på Ctrl+F9 = DELPHI4 KOMPILERAR = skapar en körbar EXE-programfil som vi sedan kör med F9 — eller bara direkt med F9 (Delphi kompilerar då först automatiskt — och kör direkt om inga fel rapporteras).

— KodFönstrets information i Unit1 har då ändrat utseende till följande:

TypeBlocket

 

Elementär flytbildsteknik — grundexempel i DELPHI4

 

— Vi ser att en ny Instans ”ExtCtrls” har tillkommit — Delphi(4) lägger INTE ALLTID automatiskt till sådana i de (mycket) speciella fallen. Men kunskaperna om dessa detaljer brukar följa med den löpande informationen, och vi får hur som helst inblick i hemligheterna vart efter.

— Dessutom har DELPHI4 lagt till de nu införda komponenterna [Avancerade programmerare kan skriva komponenter själva i VirtuellKod (som man gör i C++) typ Image1.Picture.Create förutsatt man också städar upp efter sig innan programslut för att inte göra datorn sur för andra som vill ha rent och snyggt i minnet].

 

ProjektKaralogen:

— PROJEKTKATALOGEN  (P2) innehåller nu samtliga projektfiler enligt

 

 

Ico-filen har jag själv lagt in (från gratisversioner på webben) för att vi senare ska testa hur man lägger in en sådan längst upp i programfönstret. Ikonen som syns ovan för exe-filen är den som DELPHI4 har som standard.

 

 

ExeIcon:

KODEn som krävs för att ladda in en alternativ icon I PROGRAMFÖNSTRETS RUBRIKLIST är

 

Application.Icon.LoadFromFile('FilNamnet');

 

För att också få in en alternativ icon i exe-filens iconInstans,

 

tryck Ctrl+Shift+F11 från DELPHI4, fliken Application, LoadIcon, browsa fram till Projektkatalogen (om iconfilen finns där) och tryck Öppna. DELPHI4 lägger då in den ikonen automatiskt i exe-filen,

 

— DELPHI4 förutsätter automatiskt OM INGET ANNAT ANGES att FILNAMN UTAN SPECIELLA KATALOGREFERENSER ligger i samma katalog som exe-filen.

— OM vi använder t.ex. andra instanser (typ sökprogram som är ute och snurrar på andra enheter) KAN vi i VARJE läge försäkra os om att DELPHI4 hittar HemTillVåranProjektKatalog genom programkoden

 

ExtractFilePath(Application.ExeName);

Label1:

 

— Vi ser redan nu, omgående, att VI MÅSTE HA NÅGOT ENKELT VERKTYG ATT TESTA PÅSTÅENDENA från den här författaren med, se att och HUR det verkligen fungerar

— Vi gör det genom att lägga till en Label1 (på en Panel2) på Form1,

 

 

— Synliga Namnet på Panel2 kan vi gömma undan på Object Inspector genom att lämna Caption-boxen tom.

Färgvalet för Label1 görs på Object Inspector, Color — endast OMVÄND HEXkod accepteras. Exempel:

— Här är den ljusorangea RGB-färgen 255,224,184 och motsvarande HEX FF E0 B8. DELPHI4 vill emellertid ha hexformen på omvända fasonen med inledande två nollor samt ett dollartecken

$00b8e0ff som gillas av Delphi med ändringen $00B8E0FF om man pilar ut, med motsvarande verkställd ändrad färg. Kan också justeras under programkörning med Label1.Color:= RGB(255,224,184);

Avsluta programmet med Alt+F4 eller vänsterklicka på krysset.

Eliminera ScrollBars från fönstret via Object Inspector

 

 

genom dubbelklick på +VertScrollBar och +HorzScrollBar och sätt (Ctrl+Enter) False på Visible.

 

 

och vilken skrivetikett vi sedan kan nå i olika skrivuppgifter (främst, om inget annat) genom att (»baksidan» på Object Inspector; F11, Ctrl+Tab, OnClick, Ctrl+Enter, se nedan) aktivera ett FormKlick-kodblock i DELPHI4:

— När vi klickar på Formytan, går programexekveringen DIT, och vi kan skriva in typ

 

Label1.Caption:= ExtractFilePath(Application.ExeName);

 

så att vi VET att den här författaren inte enbart pratar i nattmössan.

— »Baksidan» på Object Inspector — F11, Ctrl+Tab OnClick, Ctrl+Enter — gör att DELPHI4 automatiskt lägger till följande på Unit1;

Sist i type-blocket:

procedure FormClick(Sender: TObject);

Längst ner, närmast över end.:

procedure TForm1.FormClick(Sender: TObject);

begin

 

end;

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Skriver vi inte in något där, och kompilerar (Ctrl+F9) försvinner den inlagda proceduren — DELPHI4:s sätt att AutoRensa procedurer som inte innehåller någon verkställande programkod — detta gäller dock INTE procedurer som vi själva sedan skriver, bara DELPHI4-komponent och händelserelaterade dito. Bara sagt i parentes.

— Vi gör nu tillägget

 

procedure TForm1.FormClick(Sender: TObject);

begin

Label1.Caption:= ExtractFilePath(Application.ExeName);

ClipBoard.AsText:= Label1.Caption;

end;

Programenheter:

Tillägget med ClipBoard

 

Vi måste lägga till en Unit ”ClipBrd” till uses-blocket först, annars reagerar DELPHI4 så här om vi försöker kompilera (Ctrl+F9) eller köra direkt (F9):

 

 

FELMEDDEELANDEFÖNSTRET i DELPHI4 nederst kan vara (lite) påfrestande ibland med sina »upplysningar»: Man glömmer ett och annat, då och då i Kodningen — och lär sig med tiden uppskatta anmärkningarna: Delphi har ALLTID rätt (på ett eller annat sätt) MEN VI KANSKE INTE ALLTID FÖRSTÅR DET MED EN GÅNG, VAD DET ÄR FÖR FEL VI GÖR.

— Därför är det avgörande viktigt att nybörjaren får se EXEMPEL FRÅN REDAN FUNGERANDE ENHETER: vi vill INTE att nybörjare ska tappa modet för att man inte lyckas med en gång.

— Säkra exempel, redan testade, är avgörande viktiga.

Därifrån kan man sedan testa, modifiera och ändra för att upptäcka eget.

 

Korrekt sätt [Se UnitRubrikerna] (Vi får leta i andra avsnitt efter lösningen, här grundat på erfarenhet och sökningar i vad tillgängligt som finns) blir att först lägga till [DELPHI4 har också tidigare lagt till en enhet (via Label1) StdCtrls]

 

 

gör att jag som författare (och du som testare) slipper skriva av visuellt från Label 1, och bara kan trycka Ctrl+V och få in resultatet hit direkt (Vi kör F9 och vänsterklickar på formytan):

 

C:\Program Files (x86)\Borland\Delphi4\Projects\P2\

 

 

— OK. Nu har vi en INSTANS — FormClick — med vars hjälp vi kan ändra Programikonen. Vi gör det genom att lägga till följande programkod i proceduren FormClick:

 

procedure TForm1.FormClick(Sender: TObject);

begin

Label1.Caption:= ExtractFilePath(Application.ExeName);

ClipBoard.AsText:= Label1.Caption;

Application.Icon.LoadFromFile(

ExtractFilePath(Application.ExeName) + 'ImageReady.ico'

end;

Caption, FönsterNamn

Elementär flytbildsteknik — grundexempel i DELPHI4

Resultatet blev:

 

”Form1” läggs ut som namn på programfönstret automatiskt av DELPHI4 om inget annat anges;

— På FormCreate, eller när som helst under körning,  kan vi skriva in annat enligt det enkla

Caption:= 'Annat';

 

För vi ska få behålla den ikonen, måste den tas in (eller på annat sätt införlivas med programmet) varje gång vi startar programmet.

— Det finns särskilda RESOURCE-files för ändamålet. Men jag har ALDRIG använt dessa (på grund av vissa äventyrligheter), och tänker inte heller uppmana någon att använda sådana (det bara förkrångligar och introducerar mera än nödvändigt — men webben kanske har Delphientusiaster som [med glädje] talar om hur den resursen ska användas).

— Min lösning är att lägga ApplicationIcon.koden i ett särskilt startblock OnCreate (F11, Events, OnCreate, Ctrl+Enter):

 

DELPHI4 lägger automatiskt till (tillsammans med motsvarande procedurdeklaration i början av Unit1 under Type-blocket)

 

procedure TForm1.FormCreate(Sender: TObject);

begin

 

end;

Och vi skriver nu in

procedure TForm1.FormCreate(Sender: TObject);

var

  S: string;

begin

  S:= ExtractFilePath(Application.ExeName);

  {Extract avslutas alltid automatiskt med en BackSlash\.}

  S:= S + 'ImageReady.ico';

  if FileExists(S) then

  Application.Icon.LoadFromFile(S);

end;

 

När vi kör programmet härifrån i fortsättningen, kommer den valda ikonen alltid att framträda direkt med programfönstret.

— OM ikonfilen händelsevis inte skulle finnas på plats (if FileExists ...), hoppas bara rutinen över och standardikonen kommer fram. Utan if-satsen uppstår fel, eventuellt programavbrott, vilket vi ALDRIG ens vill se röken av: var frikostig med IF:s och Excepts och TryFinallyEnd-block — eller bara ”if not ... then exit;”: programmet går då bara ur aktuell procedur och ignorerar allt under den kommandoposten. Vi kommer säkert dit mera.

 

BildKODteknik

Åter till Image123

 

Nu kommer vi till det verkligt Avancerade i DELPHI4:

— Konsten att få Image1 att hänga med i svängarna med programfönstrets storleksändring — alltså när man börjar dra i fönsterkanterna eller kör

Alt+Space, Storleksändra.

— Jag vet inte hur mycken tid och möda jag lyckades lägga ner på den den, ändra från början med (underbara Delphi1) innan den fullständigt flimmerfria lösningen infann sig:

   Om inget annan lösning finns — kanhända någon Delphientusiast har den, men den är i så fall här helt okänd:

 

HEMLIGHETEN ligger i att AVSTÄMMA Image1 med en TBitMap — samt ”trixa” med en extra Procedur (CoFormCreate) tillsammans med ordinära OnResize (F11, OnResize, Ctrl+Enter):

 

Så här ser min lösning ut:

Närmast under TypeBlocket, en separat införd CoFormCreate. När den sedan skrivs längre ner i aktuellt verkställande kodblock I EN UNIT SOM HAR EN ASSOCIERAD FORM (här Form1) måste den skrivas ”Procedure TForm1.CoFormCreate;

 

    Procedure CoFormCreate;

    procedure FormClick(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure FormResize(Sender: TObject);

Längre ner, här alla 4 procedurer:

Alla4

Elementär flytbildsteknik — grundexempel i DELPHI4

 

procedure TForm1.FormClick(Sender: TObject);

begin

  Label1.Caption:= ExtractFilePath(Application.ExeName);

  ClipBoard.AsText:= Label1.Caption;

end;

 

 Procedure TForm1.CoFormCreate;

 var

   B: TBitMap;

 begin

 {AKTUELLA Image1MÅTTEN:}

  Panel1.BoundsRect:= Rect(0,1,Width-8,Height-Panel2.Height-30);

  Image1.BoundsRect:= Panel1.ClientRect;

 {ANPASSNING:}

  B:= TBitmap.Create;

  try

   B.Width:= Image1.Width;

   B.Height:= Image1.Height;

   Image1.Picture.Assign(B);

  finally

   B.Free;

  end;{endTry}

 {Annars grå yta vid FormResize.}

 end;{endCoFormCreate}

 

procedure TForm1.FormCreate(Sender: TObject);

var

  S: string;

begin

       Image1.AutoSize:= False;

       Image2.AutoSize:= True;

       Image3.AutoSize:= True;

       Label1.Color:= RGB(255,238,221);

       Label1.Font.Color:= clPurple;

  S:= ExtractFilePath(Application.ExeName);

  {Extract avslutas alltid automatiskt med en BackSlash\.}

  S:= S + 'ImageReady.ico';

  if FileExists(S) then

  Application.Icon.LoadFromFile(S);

  Label1.Caption:= 'ProjectP2|Successfully Initialized';

 

  with Image1.Canvas do begin

   Brush.Color:= clWhite;

   FillRect(ClientRect);

  end;

  CoFormCreate;

end;{endFormCreate}

 

procedure TForm1.FormResize(Sender: TObject);

begin

  CoFormCreate;

end;{endFormResize}

 

Försök gärna själv att testa ovanstående med modifikationer för att se om det ev. finns något alternativ att få Image1 med Panel1 att hänga med SNYGGT & PERFEKT & FLIMMERFRITT (Alla WindowsVersioner) då programfönstret storleksändras. I min referens (15 års frekvent användning): Perfekt felfri funktion.

 

 

Label1 före insättning av ljusare orange bakgrund och annan teckensnittsfärg.

Panel2 i botten följer med i fönsterändringen och anpassar sig i längd DÄRFÖR att jag i Object Inspector på Anchors [DUBBELKLICKA på +Anchorboxen, undermenyer kommer fram med alla alternativen] Panel2 har markerat akRight = True: Det mått eller den proportion som Panel2 har på Form1 vid designtillfället, kommer då att bevaras vid alla fönsterändringar.

 

 

— Men nu finns ju inte längre någon Form1-yta kvar tillgänglig att klicka på. Vi skulle ju ha den för olika »experimentella ändamål». Ahh. Ve och fasa.

— Vi kan ordna den saken galant genom Object Inspector på Panel2, nederst ovan:

— På Panel2 OnClick fäller vi via Alt+PilNer fram de alternativ som finns där; FormClick. Vi väljer den.

 

 

— I fortsättningen är nu MusKlick på Panel2 ASSOCIERAT MED musklick på Form1.

 

 

— Mera programkod tillkommer för att MED EN IMPORTERAD bild till Image1 se till att den importen också bibehålls INTAKT med motsvarande fönsterstorleksändringar.

— Vi kommer dit, strax.

— Men först måste vi sätta in den fina BildPeken, särskilt utformad (sedan 14 år tillbaka) och anpassad för precisionsarbeten,

Peken:

 

eller i varje fall se till att det finns en sådan tillgänglig.

— StandardKrysset i DELPHI4 (och andra bildprogram) är sannerligen och nämligen, min mening, inte mycket attg hurra för.

Sä här går det till att lägga till en egen skärmpekare:

1. Den måste ha en egen ico.fil;

2. Den måste ges ett specifikt FastNamn (constant);

3. Den måste laddas in som sådan genom en speciell procedur:

 

Elementär flytbildsteknik — grundexempel i DELPHI4

I ProjektKatalogen (P2) lägger vi först in en särskilt skapad bildskärmsmarkör

 

 

Ikonen för denna markör ändras i Windows sedan man besökt den aktuella katalogen.

— Anledningen till det är här helt okänd. Ständigt nya ikonbilder framträder.

— Den detaljen har dock ingen innebörd för filinnehållet.

 

Vi måste skriva en särskild procedur för det ändamålet

(Först procedurdeklarationen längst upp under TypeBlocket i sedvanlig ordning,

Procedure LoadCursors(S: string; C: Integer)), och sedan aktuellt procedurkodblock i ImplementationSektionens Procedurblock med ”TForm1.” längst fram efter Procedure:

 

Procedure TForm1.LoadCursors(S: string; C: Integer);

var

 P: PChar;

 I: Integer;{HCursor}

begin

 if FileExists(S) then

 begin

   P:= nil;

   try

    P:= StrAlloc(Length(S)+1);

    StrPCopy(P,S);

    I:= LoadCursorFromFile(P);

    Screen.Cursors[C]:= I;

   finally

    StrDispose(P);

   end; {endTry}

 end;{endIfFileExists}

end;{endLoadCursors}

 

samt deklarera den Globala PekarNamnKonstanten (efter UsesBlocket i Unit1), här (MouseCursorNo1) MC1

 

const

{MomentaryCursor:}

  MC1 = 5;

 

På FormCreate (längst ner efter CoFormCreate;) skrivs sedan in:

 

  if FileExists('Cursor1.cur') then begin

    LoadCursors('Cursor1.cur',MC1)

    Image1.Cursor:= MC1;

  else

  Label1.Color:= clAqua;

{Aqua = himmelsKlarblått

 Lime = HavsKlarGrönt

  Finns den inte ges skrikande indikering.}

 

När vi sedan kör igång (F9) med allt det ovan sagda, visar sig vår nya fina kryssmarkör bara när vi för den över Image1:

 

 

Annars den vanliga pilmarkören.

— Alternativa skärmpekare finns i många olika versioner: WindowsSystem har en hel radda inte minst (avancerat) animerade pekare (mus som äter ost, ros som växer fram, häst som springer, etc.) och som man själv kan använda om man så önskar. Se floran i Windows\Cursors.

— Delphis egen PekarBank (sätt markören i ordet Cursor och tryck F1) beskriver (delvis) sammanhangen.

— För att testa Windows olika Pekare, kopiera aktuell Pekare från Windows CursorKatalogen till ProjektKatalogewn (P2), och testa den peken genom att låna kommandona som ovan med *=aktuella PekarNamnet

 

  if FileExists('*.cur') then begin

    LoadCursors('Cursor1.cur',MC1)

    Image1.Cursor:= MC1;

 

Ctrl+V

MEN: Var kommer nu Bilden in i bilden?

MEN: Hur får vi nu in någon bild på Image1 utifrån?

Tangenten PrintScreen (PrtScn) skickar in allt som syns på bildskärmen till Urklipp;

Alt+ PrtScn tar in aktuellt aktivt programfönster.

— OK. Men hur får vi ut (standardkommando sedan datorernas urtid är Ctrl+V) något sådant från Urklipp på Image1?

   Det rena RÅA kodKommandot som utför den uppgiften SKULLE se(r) ut så här i DELPHI(4):

 

Image1.Picture.BitMap.Assign(Clipboard);

 

Elementär flytbildsteknik — grundexempel i DELPHI4

 

VI MÅSTE EMELLERTID VARA YTTERST FÖRSIKTIGA HÄR: Urklipp har (mängder med) olika FORMAT.

   Det är det första.

   Det andra är:

— Vi ska INTE ta in urklippsbilden till Image1, utan till Image2 — flytbildsInstansen — som ska läggas PÅ Image1 när vi (här, strax) använder Ctrl+Piltangenter för att flytta omkring Importen — i olika kombinationer man andra intagna bildobjekt.

— För ändamålet måste vi då aktivera (t.ex.) en ny procedur OnKeyDown för Form1

 

 

— oftast den i särklass mest innehållsrika proceduren i hela programmet, enligt min erfarenhet. Vi passar också på att lägga till en ny Global Variabel ”ClipBoardImported” som talar om var vi är och som sedan kan användas inifrån andra rutiner för säker hantering, SAMT en extra rutin för att också RENSA (F2) Image1 och nollställa för nytt.

— Koden på KeyDown (Från Autoifyllt av DELPHI4 via F11, OnKeyDown, Ctrl+Enter som ger procedurrubriken med begin och end) ser då ut så — för resultatredovisningens del har jag för tillfället lagt in en Image1.Canvas.Draw som ritar ut InKlippet på Image1 så att vi ser att allt fungerar, vi ska senare modifiera den delen och göra den verkligt avancerad — samt en liten InfoBox

 

 

för fallet att ingen BitMap finns i Urklipp:

 

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;

  Shift: TShiftState);

begin

  if Shift=[ssCtrl] then

  begin

    case Key of

  {ClipToImage:}

      Ord('V'): begin

                  if(Clipboard.HasFormat(CF_BITMAP))then begin

  {BildMåtten för Image2&3 ges automatiskt med nedanstående:}

                    Image2.Picture.LoadFromClipBoardFormat(

                    cf_BitMap,ClipBoard.GetAsHandle(cf_Bitmap),0);

                    Image3.Picture.LoadFromClipBoardFormat(

                    cf_BitMap,ClipBoard.GetAsHandle(cf_Bitmap),0);

                    Image1.Canvas.Draw(0,0,Image2.Picture.Bitmap);

                    Label1.Caption:= 'ImageFromClip OK';

                    ClipBoardImported:= True;

                  end {endIfClipIsBitMap} else

                  begin

                    Application.MessageBox(

                   'Urklipp har ingen bitmap.'

                   ,'ClipInfo',mb_OK+mb_Iconasterisk);

                  end;{endElseIfClipHasFormat}

                end;{endCtrl+V}

    end;{endCaseCtrl+Key}

  end;{endIfCtrl}

 

  if Shift=[] then

    case Key of

      VK_F2:    begin

                  with Image1.Canvas do begin

                    Brush.Color:= clWhite;

                    FillRect(ClientRect);

                    ClipBoardImported:= False;

                    Label1.Caption:= 'Image1CLEAR';

                  end;{endWithIm1Canvas}

                end;

    end;{endCaseKeyNoShifts}

end;{endKeyDown}

 

Tangenterna Ctrl+V tar in bilden från Urklipp och ritar ut den från TopLeft på Image1;

Tangenten F2 rensar bildytan för nytt och nollställer alla flaggor (ClipImported=False).

Exempel som tagit bilddump av textavsnittet närmast ovan:

 

Resultat1:

 Efter F2:

 

 

Vi behöver aldrig oroa oss för ÄVENTYRLIGA BILDMÅTT — större eller mindre än själva programfönstret går på ett ut: Windows operativsystem sköter automatiskt om alla utanföravdelningar genom Rektangelfunktionerna som ligger till grund för bildhanteringsfunktionerna.

— Vi SKULLE (här) kunna »passa på» att redan nu lägga till en bekväm bildhanteringsfunktion:

— Tangent F5 (»uppdatera») får verkställa en automatisk fönsterStorleksAnpassning till aktuellt intagen bild, om vi så vill.

— EMELLERTID. Innan vi gör det finns en mera angelägen uppgift som innefattar samma nödvändiga programkod:

— Testa (nämligen) i vänsterexemplaret ovan att ändra fönsterstorleken: bilden raderas. Ajö. Ajö.

   Hur bevarar vi en redan intagen bild vid ändring av fönsterstorleken? Mycket viktig funktion.

 

Hela lösningen består i en ORDNAD SAMMANSTÄLLNING av samtliga de flytt- och REKTANGELPARAMETERAR som krävs i synkroniseringen mellan alla Image1-3 för att få flytbilden (Im2) att fungera: alla insättningsvärden för flytbildens TopLeft (X0,Y0) och CopyRectSource och CopyRectDestination måste finnas med.

 

Vi inför först för ändamålet Globalvariablerna CopyRektanglar (TRect) CRd(estination) och CRs(ource), samt InsättningsReferensPunkten LeftTop X0 och Y0 för flytbilder (vi kommer till den mera ingående längre fram)

 

var

  CRs,CRd: TRect;

  X0,Y0:   Integer;

FlytBildsTEKNIK:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

GlobalVariabler och Konstanter ska skrivas närmast över TypeBlocket

globala procedurer skrivs inuti TypeBlocket Unit1 och utan ”TForm1.” och med inledande TForm1. till aktuella programproceduren i Implementationsektionen = huvudblocket för alla programprocedurer; Se även Delphihjälpen på Public and private declarations —

så att vi sammantaget får, i nuvarande skede från början i Unit1:

 

unit Unit1;

{ProjectP2|8Sep2014 — Im123FromStart}

 

interface

 

uses

  Windows, Messages, SysUtils, Classes,

  Graphics, Controls, Forms, Dialogs,

  ExtCtrls, StdCtrls, ClipBrd;

 

{GlobalVARIABLES|Constants .......................................:}

const

{MomentaryCursor:}

  MC1 = 5;

var

  ClipBoardImported: Bool;

  CRs,CRd: TRect;

  X0,Y0:   Integer;

 

{GlobalVARIABLES|Constants ........................................}

type

  TForm1 = class(TForm)

    Panel1: TPanel;

...

 

Anledningen att jag (här) sätter dessa variabler som globala, inte lokala (i så fall längre ner, närmast över själva sektionen med de verkställande procedurblocken) är att jag av erfarenhet redan vet att OM — mer av regel än undantag, i programmets VÄXANDE MED TIDEN — flera Unit:s kommer med i bilden, dessa behöver använda Unit1-variablerna. Är dessa lokala går inte det.

   Vi gör nu först följande förberedande tillägg direkt vid ClipImport Ctrl+V — Föregående Image1.Canvas.Draw är nu avställd och har ingen operativ funktion längre:

 

         //Image1.Canvas.Draw(0,0,Image2.Picture.Bitmap);

         X0:=0; Y0:=0;

         CRs:=Rect(0,0,Image2.Width,Image2.Height);

         CRd:=CRs;

         Image3.BoundsRect:= Image2.BoundsRect;

         Image3.Canvas.CopyMode:= cmSrcCopy;

         Image3.Canvas.CopyRect(CRd,Image1.Canvas,CRs);

         Image1.Canvas.CopyMode:= cmSrcCopy;

         Image1.Canvas.CopyRect(CRd,Image2.Canvas,CRs);

 

 

Sista raden explicit ERSÄTTER föregående tillfälliga resultatritning ”Image1.Canvas.Draw(0,0,Image2.Picture.Bitmap);”. Vi kan bara bocka för = avställa den med två delstreck (DELPHI kursiverar och mörkblåfärgar allt som inte är kod)

//Image... eller inom listparenteser

{Image ...} eller mellan två stjärnor inom rundparenteser

(*Image ...*).

   Vi testar först att det utlovade fungerar:

 

 

IJÄss.

— OK. Vad är Hemligheten nudå med att få ha min bild KVAR vid ändring av fönsterstorlek?

— Vi utvidgar föregående enkla kod på FormResize

 

procedure TForm1.FormResize(Sender: TObject);

begin

  CoFormCreate;

end;{endFormResize}

Elementär flytbildsteknik — grundexempel i DELPHI4

 

till — du måste se det för att tro det: Tryck PrtScn, Starta P2, Tryck Ctrl+V, Bildskärmsdumpen kommer in TopLeft; tryck Alt+Space för att fälla ned fönsterändringsmenyn, tryck S för Ändra storlek; pila markören till HögerBotten; pila Höger Neråt;

— vartefter fönsterstorleken ökas, syns nu alltmer av den intagna hela skärmbilden; Testa också Alt+Space med X för Maximera: hela skärmdumpen syns — och tillbaka med Alt+Space och Enter för ÅterställFönsterstorleken till föregående; inte ett enda flimmer; helt perfekt rent:

 

 

 

procedure TForm1.FormResize(Sender: TObject);

var

  BR,CRsB,CRdB: Trect;

  B: TBitmap;

begin

{FÖRBEREDER intagning av Image1:}

       B:= TBitmap.Create;

       try

{BILDYTAN TBitmap:}

        BR:= BitmapRect(Image1.ClientRect,B);

{Lägger in (föregående) Image1 på Bitmap'en:}

        B.Assign(Image1.Picture.Graphic);

        B.Canvas.CopyRect(CRd,Image3.Canvas,CRs);

 

{KÖR NYA KOMPONENTPLACERINGAR:}

        CoFormCreate;

{ANPASSAR nya bildmått:}

        CRsB:=Rect(0,0,Image2.Width,Image2.Height);

        CRdB:=CRsB;

        Image1.Canvas.CopyMode := cmSrcCopy;

        Image3.Canvas.CopyRect(CRdB,Image1.Canvas,CRsB);

{Lägger tillbaka Im1BeforeResize på nya Im1:}

        Image1.Canvas.CopyRect(BR,B.Canvas,BR);

{Kopierar FlytBildsRektangeln av Im1(=Im2-ytan med Im1-bilden) till Im3:}

        Image3.Canvas.CopyRect(BR,B.Canvas,NewOR(BR,X0,Y0));

       finally

        B.Free;

       end;

{Återställer FlytBilden (Im2) på Im1:}

       //Image1.Canvas.CopyMode := cmSrcAnd;

       Image1.Canvas.CopyRect(CRd,Image2.Canvas,CRs);

end;{endFormResize}

 

Anledningen varför jag (här) skrivit ut CopyMode:= cmSrcCopy är bara för att (i mina allmänna DELPHIrefrenser) SÄKRA sådan kopieringsmod då programkoden i övrigt är (oerhört) välbesutten på många andra typer: Standard från start är cmSrcCopy för en TImage eller TBitMap, men ändras den för den komponenten eller instansen, kvarstår den inställningen också tills ändrad igen.

— Hur de olika sätten fungerar får vi se först när vi kan kombinera flera olika bildintag över, i eller genom varandra.

— Vi ska strax försöka komma dit.

 

med (TypeBlocket, början Unit1: global som kan nås av alla kommande Units) [Se BMR]

 

    function BitMapRect(R:TRect; var B:TBitmap):TRect;

    function NewOR(R: TRect; X,Y: integer): TRect;

 

som i ImplementationBlocket (aktuella funktioner och procedurer i Unit1) har formen (+TForm1.)

 

    {Skapar en ny, LeftTop-nollad, TRect som bildytan för

    en medsänd TBitmap:}

    function TForm1.BitMapRect(R:TRect; var B:TBitmap):TRect;

    begin

     OffsetRect(R,-R.Left,-R.Top);

     B.Width:=  R.Right;

     B.Height:= R.Bottom;

     BitmapRect:= R;

    end;

    {Skapar en ny, flyttad, TRect från en medsänd:}

    function TForm1.NewOR(R: TRect; X,Y: integer): TRect;

    begin

     OffsetRect(R,X,Y);

     NewOR:= R;

    end;

 

Se särskilt beskrivningen i BMR. Användbarheten i speciellt BitMapRect-funktionen är i min erfarenhet utomordentligt omfattande i Delphiprogrammeringen: ytterst stor användbarhet.

 

FönsterAnpassning, F5

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Anpassning F5 — programfönstrets storlek anpassas till importerad bildstorlek

 

minsta: Image1.Height = 50p:  WindowsSystem ser automatiskt till att MINST avslutningsknappen finns med.

 

 

Form1ToppListen tar up 23pixels [eg.22, men vi har här lagt till en extra till Image1-kanten av designskäl]:

Panel2 ytterligare + 2×3 pixel i rammarginalen för programfönstret

 

Nu kan vi förverkliga fönsteranpassningen till den importerade bildstorleken, om så önskemål finns.

— På FormKeyDown skriver vi då in koden (var iW,iH,x,y: Integer; tillagt på FormKeyDown):

 

 {ANPASSA EFTER IMPORT · 29Jun2011|9Sep2014:}

      VK_F5:    begin

                  if not ClipBoardImported then exit;

                  iW:= Image2.Width +2;

                  iH:= Image2.Height+2;

                  Panel1.Width:=  iW;

                  Panel1.Height:= iH;

                  x:= iW + 6 +1;

 

                  if iH > Panel2.Height

                  then

                  y:=

                  iH +

                  + Panel2.Height

                  + 23   + 6 +1

                  else

                  y:=

                  Panel2.Height

                  + 50   + 6 +1;

 

                  if x > Screen.Width  then y:=Screen.Width;

                  if y > Screen.Height then y:=Screen.Height;

                  Width:= x;

                  Height:= y;

 

                  if BoundsRect.Right > Screen.Width then

                  Left:= Left - (BoundsRect.Right  - Screen.Width);

                  if BoundsRect.Bottom > Screen.Height then

                  Top:=  Top  - (BoundsRect.Bottom - Screen.Height);

{Ta om Im2Kopieringen:}

                  ClipBoard.Assign(Image2.Picture);

                  {RENSAallt:}

                  Key:= VK_F2;

                  FormKeyDown(Self,Key,[]);

                  {TaOmImporten:}

                  Key:= Ord('V');

                  FormKeyDown(Self,Key,[ssCtrl]);

                end;{endF5}

 

Width och Height utan den sedvanliga komponentspecificeringen behöver aldrig göras om komponenten är Form1.

— Ovanstående kan skrivas med samma funktion: Form1.Width:= och Form1.Height:= .. .

 

Direkt efter ClipImport med Ctrl+V:

 

 

Efter F5:

 

Perfekt.

— Jag har här lagt till en marginal högerBotten på 1 pixel som visar Image1-bakgrunden, här vitt, och som ger lite extra relief för mörkare bildImporter högerBotten.

 

BildEXPORT, Ctrl+I

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Rutin för BildExport — Ctrl+I

Vi vill nu också DIREK förverkliga EXPORT av aktuell bildyta till Urklipp. Tillägget nedan ImageToClip på FormKeyDown [Ctrl] — vi lägger till variabler lokalt i FormKeyDown vartefter de behövs, här en B: TBitMap; och en R: TRect; :

 

var

  B: TBitMap;

  R: TRect;

  iW,iH,x,y: Integer;

begin

  if Shift=[ssCtrl] then

  begin

    case Key of

  {ImageToClip:}

      Ord('I'): begin

                  B:= TBitmap.Create;

                  try

                   R:= Image1.ClientRect;

                   BitMapRect(R,B);

                   B.Canvas.CopyMode:= cmSrcCopy;

                   B.Canvas.CopyRect(R,Image1.Canvas,R);

                   Clipboard.Assign(B);

                  finally

                   B.Free;

                  end;{endTry}

                  Label1.Caption:= 'ImageToClip|OK';

                end;{endCtrl+I}

  {ClipToImage:}

      Ord('V'): begin

                  if(Clipboard.HasFormat(CF_BITMAP))then begin

                ...

 

Vi testar resultatet genom att köra Ctrl+I från en intagen bild Ctrl+V, minska fönsterstorleken, köra Ctrl+V och sedan F5 som bevisar att ursprunget återtas: ... IJjjj .. Äss. Stämmer bra det.

   (Det händer ibland att det blir ... IJjjj .. ävlar — man missar ibland. Bara att ta paus och försöka med BättreKod).

 

PilotDISPLAY:

Indikering för intagen bildstorlek och aktuella skärmkoordinater för Peken

 

 

DatorPilotens MinimiPanel:

1. Färgen under Peken — en liten [topp]ruta som ALLTID visar vilken färgen är under bildmarkörens HotSpot

2. Pekens ImageKoordinater X;Y — vi måste ha en OnMouseMove-rutin för det

3. Bildmåtten efter import från Urklipp — vi behöver hur som helst en extra panel under programfönstrets topplist

 

Innan vi nu går vidare måste vi ha PILOTCERTIFIERANDE BASINFO — paneldata — som talar om för oss var vi är i framstegen:

0. En liten ruta som visar aktuell FÄRG under peken — mycket användbart (enkla färgval, bl.a. vid ritning)

1. En Display som visar ImportMåtten från bilden i Urklipp;

2. En allmän Peka(X;Y) som visar var pekarKrysset befinner sig på Image1, bildytan som är vårt arbetsbord.

 

 

Jag sa ju det:

— DELPHI4 i Windows7 är Kanon.

 

Form1 Project P2 ovan efter import av en enklare RGB-palett, samt insatta 3 nya paneler: Panel3 för färgvisning under Peken, Panel4 för XY-koordinaterna och Panel5 för Importens bildmått. Nöj dig inte med mindre.

— KODEN på Image1MouseMove (Image1, Object Inspector, OnMouseMove, Ctrl+Enter):

 

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,

  Y: Integer);

begin

 

                  Panel4.Caption:=

                  IntToStr(X) + ';' +

                  IntToStr(Y);

                  V:= Image1.Canvas.Pixels[X,Y];

                  Panel3.Color:= V;

  {Eliminerar marginellt flicker:}

                  Panel3.Refresh;

 

end;

 

Variabeln V: TColor Global; samt infogat på ClipToImage FormKeyDown Ctrl+V för Panel5:

 

                  Panel5.Caption:=

                  IntToStr(Image2.Width)+';'+

                  IntToStr(Image2.Height);{}

end;

Elementär flytbildsteknik — grundexempel i DELPHI4

 

och på F2 efter ClearIm1,

 

Panel5.Caption:= 'Dimensions';

 

så att inga siffror »ligger och skräpar» sedan sista Importen raderats.

 

MarkörACCELERATORER:

Inrättning av markörflyttning med piltangenter och acceleratorer (CursAcc)

 

Innan vi går vidare måste vi nu koppla ihop det (snygga) ovan med en EXAKT PekarNavigering — inte minst för ändamålet att KUNNA pricka in exakta färgmakeringar i olika tillval (färgenUnderPeken), utan mera allmänt för exakta bildarbeten med exakta passningar och positioner: det hänger på pixeln. Utan det kan vi lika gärna kasta ut datorn direkt: värdelöst SKRÄP.

— Tänk KLASSISKT:

— Vi som är uppfödda med Penna, Linjal, Passare som GRUNDBLOCK, vill ALLTID ha MINST »en fungerande ritpenna i bröstfickan»: räta linjer, enkla figurer PÅ STUBINEN.

— Vi ska återkomma till den detaljen, strax.

 

Betingelser för att realisera funktionerna MARKÖRFLYTTNING:

1. FormKeyUp måste introduceras för att nollställa den allt växande heltalsvariabeln CursAcc efter Piltangerna (KeyDown), annars kommer Peken att accelerera iväg för evigt med allt högre hastigheter och allt större steglängder.

2. En separat MarkörMove-procedur måste inrättas som styr funktionen via KeyDown-tangenterna PilUpNerVäHö.

3. En särskild procedur som uppdaterar Image1-Måtten — kopplar till Rezise:

 

  Procedure TForm1.SetSCRIm1Rect;

  begin

{GENERELLT Image1RectDimensions}

       SCRIm1.TopLeft:=Image1.ClientOrigin;

       SCRIm1.BottomRight:= Point(

       Image1.ClientOrigin.X +

       Image1.ClientWidth  + 1,

       Image1.ClientOrigin.Y +

       Image1.ClientHeight + 1 );

  end;{endSetSCRIm1Rect}

 

 

Proceduren ovan används (så småningom ju mer avancerat funktionerna flätas samman) av flera instanser i flytbildshanteringen, och gör sig därför bäst som fristående, global, procedur som kan användas av alla.

 

 

— Test visar att FormCreate ALLTID genomgår Resize-blocket, i vilket fall, och vi kan därför förlägga ett separat anrop till Image1UppdateringsRutinen ovan DIREKT i FormResize (sist: SetSCRIm1Rect;): Därmed ges Image1-dimensionerna direkt i SCRIm1-rektangeln från programstart: och sedan vidare med varje storleksändring av programfönstret;

4. Fyra separat BEKVÄMA positionerare behövs (ibland, bekvämt) för att sätta peken i endera bildhörnet; vi använder här tangenterna HOME(LeftTop), END(LeftBottom), PageUp(RightTop) och PageDown(RightBottom) för det;

 

— KODEN i DELPHI4 för att realisera ovanstående:

 

NyaGlobalaVariabler:

 

  SCRIm1:  TRect;          {Image1Rectangle}

  CursAcc: Integer;        {MarkörAcceleratorn}

 

MarkMoveProceduren, Global (TForm1. i TypeBlocket, utan TForm1. i procedurblocket) — Programexekveringen skickas hit från KeyDown om rena piltangenter utan Ctrl och Shift:

 

  {MARKÖRFLYTTNINGEN|orig.Rot1:}

  Procedure TForm1.MarkMove(Key: word);

  var

    P:   TPoint;

    X,Y,W,H: Integer;

  begin

   with Image1 do

   begin

    X:= ClientOrigin.X;

    Y:= ClientOrigin.Y;

    W:= ClientWidth;

    H:= ClientHeight;

   end;

   GetCursorPos(P);

{DIREKTREFERENS I HELSKÄRMSKOORDINATER:}

   if (PtInRect(SCRIm1,P)=True) then begin

    case Key of

         VK_RIGHT: begin if P.X+CursAcc<X+W then begin

                   P.X:= P.X + CursAcc; Inc(CursAcc);

                   end else CursAcc:= X + W - P.X - 1;

                   end;{endRight}

         VK_LEFT:  begin if P.X-CursAcc+1>X then begin

                   P.X:= P.X - CursAcc; Inc(CursAcc);

                   end else CursAcc:= P.X - X;

                   end;{endLeft}

         VK_UP:    begin if P.Y-CursAcc+1>Y then begin

                   P.Y:= P.Y - CursAcc; Inc(CursAcc);

                   end else CursAcc:= P.Y - Y;

                   end;{endUp}

         VK_DOWN:  begin if P.Y+CursAcc<Y+H then begin

                   P.Y:= P.Y + CursAcc; Inc(CursAcc);

                   end else CursAcc:= Y + H - P.Y - 1;

                   end;{endDown}

    end;{endCaseKey}

  {VERKSTÄLLER:}

    SetCursorPos(P.X,P.Y);

   end;{endIfPtInRect}

  end;{endProcedureTForm1.MarkMove}

  {NOTERING.

  1   För att markörflyttningen ska fungera måste en särskild

      rutin för bildkoordinaternas uppdatering (via SCRIm1)

      finnas på den särskilda proceduren vid OnPaint|Resize.

  2.  CursAcc måste återställas till stegning för 1 pixel

      på FormKeyUp, annars steppas allt större distanser i

      varje steg.}

Elementär flytbildsteknik — grundexempel i DELPHI4

 

FUNKTION:

 

 

När vi trycker ner en piltangent, här PilHöger, och håller tangenten nedtryckt, ackumuleras flyttstegningen successivt med tiden (värdet i CursAcc ökar), och Peken drar iväg allt snabbare över bildskärmen. När den når fönsterkanten, retarderar den (snabbt) och stannar.

— Det gör det LÄTT för oss att SNABBT hitta/nå EXAKTA positioner — med en kombination av MusRörelse och Piltangenter.

— Koden på KeyDown för HomeEndPageUpDown, Peken i endera bildhörnet:

 

      VK_PRIOR: begin {PageUp | HögerÖvre:}

                  SetCursorPos(Image1.ClientOrigin.X+Image1.ClientWidth-1,

                  Image1.ClientOrigin.Y);

                  exit;

                end;

      VK_NEXT:  begin {PageDown | HögerNedre:}

                  SetCursorPos(Image1.ClientOrigin.X+Image1.ClientWidth-1,

                  Image1.ClientOrigin.Y+Image1.ClientHeight-1);

                  exit;

                end;

      VK_END:   begin {PageDown | VänsterNedre:}

                  SetCursorPos(Image1.ClientOrigin.X,

                  Image1.ClientOrigin.Y+Image1.ClientHeight-1);

                  exit;

                end;

      VK_HOME:  begin {PageDown | VänsterÖvre:}

                  SetCursorPos(Image1.ClientOrigin.X,

                  Image1.ClientOrigin.Y);

                  exit;

                end;

DelResultat:

Ctrl+V       Importera Bild FrånUrklipp

Ctrl+I        Exportera HelaBildytan TillUrklipp

F2            Rensa Bildytan

F5            Anpassa programfönstret till ImporteradBild

 

Piltangent  Fri, accelererad markörflyttning, eller exakt enskild pixelstegning

Home        Peken LeftTop

End           Peken LeftDown

PageUp      Peken RightTop

PageDown  Peken RightDown

 

 

Jag har också lagt in VK_HOME-kommandot på FormCreate så att programförnstret alltid startar upp med peken där.

(Detta grepp är mindre lämpligt med hänsyn till klickutflykter för andra programfönster på bildskärmen. Jag har t.v. bockat av den delen då vi i vilket fall bara behöver trycka HOME för att få se peken LeftTop med aktivt P2).

— För Programnamnlisten, se Caption.

 

Flytbilden, Tabell

Målet nått 9Sep2014 — [det tog 5 dagar att sammanställa]

 

Flytbilden

 

Nu är vi klara för att förverkliga drömmen:

— Importerade UrklippsBilder ska kunna flyttas på, över, i och genom bildytan Im1 efter de olika ELEMENTÄRA »transportsätten».

— Vi kallar här ett sådan flyttbart bildobjekt för en flytbild.

   Vi studerar det.

 

 

Ctrl+Pilar      flyttar UrklippsImporter Ctrl+V över bildytan i FLYTSTEG om Ctrl+NumPad|1 2 3 5 9 antal pixels 1 5 20 halvsida(höjd) helsida(höjd);

— Från programstart är flytintervallet inställt på 20 pixels (min erfarenhet, bästa kompromissen för alla fall i grov flyttning).

— Intaget ovan från hel skärmbild (PrtScn), textområdet har flyttats så att bara text syns, sedan en separat ClipExport från annat program med RGB-paletten, denna in via Ctrl+V sedan flyttad med Ctrl+PilHöger i CopyMode standard cmSrcCopy: Flytbildens hela bildrektangel ligger täckande underlaget. Vi ska senare se hur också samtliga övriga flytbildsSÄTT kan förverkligas via DELPHI4-KOD. Den delen kräver att vi måste genomgå alla flytbildssätten i ett gemensamt block (s.k. FLYTBILDSFLAGGOR: dessa styr tillvalen och kräver extra PilotPaneler i DISPLAY för vår Info).

— Genom speciell kodning [vidare nedan: MarkMove(0)], uppdateras här även färgrutan nedrevänster som visar färgen under peken då flytbildens färger passerar i flytten — utan någon MouseMove (»It’sMacig»).

 

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Koden i DELPHI4 som slutligen förverkligar flytbilden som ovan ser ut så här — KeyDown i Ctrl-blocket med tillagd globalvariabel

ArrowStep: Integer; 20pixels från programstart [ASMM ännu bara = 1; –1 ger omvända flytriktningar]:

 

      VK_LEFT,VK_UP,VK_RIGHT,VK_DOWN:

                begin

{ASMM·piltangentsvändare|ArrowSwapperMoveMore|, ArrowStep·1,5,20 pixels:}

{PREPARE SourceDestinationRECTANGELS:}

                  CRs:=Bounds(0,0,Image2.Width,Image2.Height);

                  CRd:=Bounds(X0,Y0,Image2.Width,Image2.Height);

{ÅTERSTÄLLER Image1|Lägger ut föregående InKopia i Im3:}

                  Image1.Canvas.CopyMode:= cmSrcCopy;

                  {cmSrcAnd här = avtryck efter varje flyttning.}

                  Image1.Canvas.CopyRect(CRd,Image3.Canvas,CRs);

{VERKSTÄLL FLYTSTEG:}

                  case Key of

                   VK_LEFT:   X0:=X0-ArrowStep*ASMM;

                   VK_RIGHT:  X0:=X0+ArrowStep*ASMM;

                   VK_UP:     Y0:=Y0-ArrowStep*ASMM;

                   VK_DOWN:   Y0:=Y0+ArrowStep*ASMM;

                  end;{endCaseKey}

{UPPDATERAR Destinationskoordinaterna:}

                  CRd:=Bounds(X0,Y0,Image2.Width,Image2.Height);

{SPARAR UNDAN originalytan, CRd/s omvända:}

                  Image3.Canvas.CopyRect(CRs,Image1.Canvas,CRd);

{FLYTBILDEN|Im2 LÄGGS PÅ NY PLATS:}

                  Image1.Canvas.CopyRect(CRd,Image2.Canvas,CRs);

                  MarkMove(0);

      {MarkMove(0)|AktiverarMouseMove via en DoNothing.

       Därmed uppdateras Färgrutan, samt övriga data

       som (ev.) finns på Im1 i anslutning till olika

       PekRörelser/Flytbilder.}

                  exit;

                end;{endIf Ctrl+Arrows}

 

Förstummande galant.

— GRUNDJOBBET till allt det ovan — nu använt under mer än 15 år — gjordes (faktiskt) på 16 bitars Delphi1: värdens underbaraste MasterProgram (slutet av 1990-talet, Windows 95), just på grund av dess NÄRA anslutning till MIKROPROCESSORN: 16-bitars programmering som tvingade mig att lösa problemen med sömlösa övergångar i BitMaps med gränsblock om 65535Byte — och som ibland förorsakade kommersiella WindowsKrascher för Microsofts egna programvaror (MsWorks Utskrifter) [som bara bevisade hur marknaden SLARVAR med KOD (Microsoft kan ännu i denna dag inte lösa ELEMENTÄRA programuppgifter: jämför SökMotorerna på datorns hårddisk: rena katastrofen i Microsoft)].

 

RitaMusHöger

 

Enkelt ritverktyg tillagt. MusHögerNer. Alltid tillgängligt. MED piltangenter som Kan Accelerera. Rakt.

 

 

Följande tillägg på Image1MouseMove ger ovanstående enkla MANUELLA MED ACCELERERANDE PILTANGENTESFUNKTIONEN INKLUDERAD pennritningsfunktion: Höger musknapp ner

— när som helst. AnyTimeYouWant:

 

var

  C1: Integer;

procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,

  Y: Integer);

begin

...

                  {DRAW SIMPLE LINES|MouseRight:}

                  if GetKeyState(VK_RBUTTON)<=-127 then begin

                   with Image1.Canvas do begin

                     if C1=1 then

                     begin

                     Pen.Style:= psSolid;

                     Pen.Color:= 0;

                     Pen.Width:= 1;

                     LineTo(X,Y);

                     end else begin

                     MoveTo(X,Y);

                     C1:= 1;

                     exit;

                     end;

                   end;{endWithIm1Canvas}

                  end{endIfMouseRight}else

                  C1:= 0;

 

Separata variabler (var) som deklareras omedelbart före en procedur ses av (bara) den proceduren (och alla efterföljande) som en »global» variabel. Sätter vi C1 som en variabel i själva proceduren, fungerar inte koden därför att värdet på C1 då förloras med programmets exekverande procedurutgång [DELPHI4 nollställer i allmänhet alla procedurutanförstående variabler från programstart — men man bör inte ta det för säkert. Säkert är dock att alla reguljärt globalt deklarerade variabler ALLTID nollas från programstart av DELPHI4. Se vidare i DelphiHjälpen (Declaring variables)].

 

MoveMore:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

 

Ctrl+M      Reverserar flytriktningen via piltangenterna Move|More:

— M-panelen ovan (Panel6) har lagts till med koden nedan på Ctrl-FormKeyDown-blocket

 

  {ArrowsSwapMoveMore|ASMM:}

      Ord('M'): begin

                  ASMM:= - ASMM;

                  if ASMM=1 then

                  Panel6.BevelOuter:= bvRaised else

                  Panel6.BevelOuter:= bvLowered;

                end;

 

ASMM=1 från programstart: flyttning av importbilder från urklipp lämpat för bilder mindre än fönsterstorleken: MOVE.

— Större bilder vill man ser mer av MED SAMMA TANGENT som då uppför sig rebelliskt »åt andra hållet».

— Ett tryck på Ctrl+M ändrar den situation och ger det man vill ha: showmeMORE.

— Notera att ASMM-värdet kopplar (se längre upp) bildflyttningens X0|Y0-ArrowStep*ASMM.

 

FleraÖppnaFönster, MultiWin — 10Sep2014

 

Flera öppna programfönster

 

Vi kan öppna i princip hur många programfönster som helst av typen som skapas av DELPHI4-Windowsprogram. Enda problemet är att vi måste utforma något SÄTT att dels skilja dem åt — här genom numrering — och dels kunna identifiera vad som gäller speciellt vid programavslutning, om uppgiften gäller att spara undan data som man sedan vill kunna återuppta vid en senare programstart. Här är DelphiKoden för det:

 

 

 

 

Öppnas n stycken fönster och ett i högen klickas av, kommer nästa programfönster som startas upp att ta platsen för det fönster som klickats av med lägsta ordningsnummer: inga tomrum tillåts.

 

 

 

Koden nedan (testat speciellt på det krångliga vildsinta operativsystemet Windows Vista — tenderar att gruppera program med samma ursprung)

har

[med nuvarande 10Sep2014 viss reservation för WindowsVista: min Vistadator har slutat fungera efter 7 år, och den delen kan här inte testas längre med den numera modifierade Delphikoden nedan

[avställt {(NumWin=0)and} i if{(NumWin=0)and}(MultiWin=False)then]

testats upp till Windows 7 och har visat sig fungera galant:

 

1. Vi behöver först en särskild procedur som skannar av vilka öppna Windowsprogram som finns (GlobalProceduren deklareras som vanligt i TypeBlocket överst i Unit1 som nedan men utan TForm1.), NumWin: Integer; är global (deklareras efter UsesBlocket, Unit1):

Procedure TForm1.CheckMultiWin;

var

  T:       TStringList;

  S:       string;

  N,Z,X,C: Integer;

  PC:      PChar;

begin

       T:= TStringList.Create; T.Sorted:= True;

       NumWin:= 0; C:= 0; Z:= 1;

       PC:= StrAlloc(51);

       X:= GetWindow(Form1.Handle,GW_HwndFirst);

       try

{SKANNA AV ALLA ÖPPNA WINDOWSFÖNSTER:}

         repeat

           Inc(C); X:= GetWindow(X,GW_HwndNext);

           GetWindowText(X,PC,50);

           S:= StrPas(PC);

{INGEN FRÅN FÖRSTA:}

           if Pos(' P2 | Form1 ',S)>0 then

           begin

            Inc(NumWin);

           {Caption:= '  P2 | Form1 |  — ' }

           {           123456789012345678 :}

            Delete(S,1,18);

            T.Add(S);

{REDAN BEFINTLIGA FÖNSTERNUMMER N-1:}

            N:= StrToInt(S) +1;

{FYLLER PÅ MED +1 EFTER SENAST HÖGSTA VÄRDE:}

            if N>Z then Z:= N;

           end;

         until(X=0)or(C>=1000);

         {ClipBoard.AsText:= IntToStr(C)|Test visar C=242 vid X=0.}

{SÄKRA FÖRST RAKA NUMRERINGEN|Om inget annat gäller:}

         NumWin:= Z;

{KOLLA OM LUCKOR FINNS I NUMRERINGEN|OmSå, ta närmast lägsta lediga:}

         for N:= 0 to T.Count-1 do

         if StrToInt(T[N])<> N+1 then

         begin

           NumWin:= N+1;

           Break;

         end;

       finally

         StrDispose(PC);

         T.Free;

       end;

       if NumWin-1>1 then MultiWin:= True else MultiWin:=False;

       {Numreringen för sista fönstret kommer att sluta på NumWin=2:

       — Första sökningen på GetWindowText(X,PC,50) ger noll eftersom första

       programfönstret ännu inte finns. Då sedan (sista) programmet avslutas,

       finns redan en förekomst, och som räknas upp internt i ifPos-blocket.}

end;{endCheckMultiWin}

 

 

På FormCreate ersätter vi sedan föregående enkla ”Caption:= ' P2 | Form1” med det mera avancerade

 

 

{SEPARATA FÖNSTERNAMN FÖR FLERA ÖPPNADE PROGRAMFÖNSTER:}

       CheckMultiWin;

       Caption:= '  P2 | Form1 |  — ' + IntToStr(NumWin);

{DELPHI4Test2014|4Nov2013|10Sep2014|P2.}

{WindowsVista KAN försöka stänga flera (9+) öppna fönster som GRUPP — vilket resulterar i FEL:

CannotCreate DATA.txt-file på FormClose: Bara ETT programfönster åt gången får stängas:

   FÖRKLARING:

   — Om var och en av nst öppnade P2 försöker spara data vid Close för åtkomst vid nästa öppning,

   är det givet att »systemet pajar».

   LÖSNING:|4Nov2013 — se tillägget MultiWin-flaggan, FormClose. TestatOK till 12st. Hela gruppen stänger utan protest.}

{Forts. FormClose.}

       Left:= (Screen.Width -  Width)  div 2 + (NumWin-1)*20;

       Top:=  (Screen.Height - Height) div 2 + (NumWin-1)*20;

 

tillsammans med en GlobalVariabel MultiWin: Bool;.

— Vi lägger sedan till en FormClose via Object Inspector Form1, F11, OnClose, Ctrl+Enter: Mellan begin-end skriver vi in, samt lägger till variabler:

 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

var

  S:   string;

  TS:  TStringList;

begin

   exit;

{REKOMMENDERAT FÖR DEN SOM VILL FORTSÄTTA PROGRAMUPPGIFTEN SJÄLV:}

   {Använd följande rutinblock — ge alternativt namn — om uppgiften

   är att spara undan programdata som ska användas nästa gång programmet

   startar upp — typ använda färger eller värden eller text eller vad

   det kan vara:}

{SEPARAT PROCEDUR — används på FormCreate och FormClose:}

       CheckMultiWin;

{Här exekveras TestVillkoret:}

{Se MultiWin på FormCreate|Endast sista CloseFönstret berörs:}

       if(MultiWin=False)then

       begin

{SaveDATA:}

         TS:= TStringList.Create;

         try

           SetCurrentDirectory('C:\');

           S:= ExtractFilePath(Application.ExeName);

           TS.Add('Data1');

           TS.Add('Data2');

           TS.Add('Data3');

         finally

           TS.SaveToFile(S+'DATA.txt');

           TS.Free;

         end;

       end;{endIfOnlyOneLastOpenProgramWindow}

end;{endFormClose}

 

Modifiera, utvidga eller ändra TS.Add-posterna efter egna önskemål.

— Bockas exit;-raden av (//exit; eller {exit;}) kommer en ny fil DTA.txt att läggas in i projektkatalogen med raderna.

 

Data1

Data2

Data3

 

Flytsätten, MoveCOPY och MoveAND

Elementär flytbildsteknik — grundexempel i DELPHI4

 

 

Flytbildens olika transportsätt över bildytan

 

— Ovanstående resultat för flytbilden motsvarar MoveCOPY: flytbildens totala UrklippsRektangel flyttas över den underliggande bildytan som en enskild fast yta.

— Vi inför nu först anpassad DELPHIkod för att också få den andra ELEMENTÄRA flytbildsmaken med:

— MoveAND: flytbildens pixels AND-as tillsammans med den underliggande bildens pixels:

 

1. Vi inför först två nya paneler, Panel7(C) och Panel 8(W)

 

 

C:     upphöjd, Indikerar MoveCOPY = fristående flytbildsobjekt med separata pixelkanaler

        nedsänkt, Indikerar MoveAND = kombinerar pixels hos underlag OCH flytbild

        tangent C togglar=växlar mellan dessa — vi återkommer till W (SkipWhite)

 

2. Vi anpassar kod med tre nya globala variabler

 

  CopMod:               TCopyMode;

  FleetState,SkipWhite: Integer;

 

och en särskild global procedur för uppdatering UpdateMergeFlags,

 

Procedure TForm1.UpdateMergeFlags;

begin

  if FleetState=0 then

{MoveAND:}

  Panel7.BevelOuter:= bvLowered else

{MoveCOPY:}

  Panel7.BevelOuter:= bvRaised;

  if SkipWhite=-1 then

  Panel8.BevelOuter:= bvRaised else

  Panel8.BevelOuter:= bvLowered;

{Om MoveANDgäller har SkipWhite ingen funktion:}

  if FleetState=0 then

  Panel8.BevelOuter:= bvNone;

{}

end;

 

med motsvarande tangentkommandon på FormKeyDown, blocket utan skifttangenter, CaseKeyBlocket,

 

 {MoveCOPY|AND|10Sep2014:}

      Ord('C'): begin

                  if FleetState=0 then

 {MoveCOPY:}      FleetState:= 1 else

 {MoveAND:}       FleetState:= 0;

                  UpdateMergeFlags;

                end;{endC|A}

 {SkipWHITE|10Sep2014:}

      Ord('W'): begin

                  SkipWhite:= -SkipWhite;

                  UpdateMergeFlags;

                  {ImmediateKeyResponse:}

                  {I:=ArrowStep;

                  ArrowStep:=0;

                  W:= VK_DOWN;

                  FormKeyDown(Self,W,[ssCtrl]);

                  ArrowStep:=I;{}

                end;

 

med motsvarande StartVärden på FormCreate,

 

{MoveCOPY|TakeWhite:}

       FleetState:= 1;

       SkipWhite:=  1;

 

och VERSKTÄLLANDE på BildFlyttningen, FormKeyDown, här de nya posterna markerade med orange och gult,

 

      VK_LEFT,VK_UP,VK_RIGHT,VK_DOWN:

                begin

                  if FleetState=0 then CopMod:=cmSrcAnd else CopMod:=cmSrcCopy;

{ASMM·piltangentsvändare|ArrowSwapperMoveMore|, ArrowStep·1,5,20 pixels:}

{PREPARE SourceDestinationRECTANGELS:}

                  CRs:=Bounds(0,0,Image2.Width,Image2.Height);

                  CRd:=Bounds(X0,Y0,Image2.Width,Image2.Height);

{ÅTERSTÄLLER Image1|Lägger ut föregående InKopia i Im3:}

                  Image1.Canvas.CopyMode := cmSrcCopy;

                  {cmSrcAnd här = avtryck efter varje flyttning.}

                  Image1.Canvas.CopyRect(CRd,Image3.Canvas,CRs);

{VERKSTÄLL FLYTSTEG:}

                  case Key of

                   VK_LEFT:   X0:=X0-ArrowStep*ASMM;

                   VK_RIGHT:  X0:=X0+ArrowStep*ASMM;

                   VK_UP:     Y0:=Y0-ArrowStep*ASMM;

                   VK_DOWN:   Y0:=Y0+ArrowStep*ASMM;

                  end;{endCaseKey}

{UPPDATERAR Destinationskoordinaterna:}

                  CRd:=Bounds(X0,Y0,Image2.Width,Image2.Height);

{SPARAR UNDAN originalytan, CRd/s omvända:}

                  Image3.Canvas.CopyRect(CRs,Image1.Canvas,CRd);

{FLYTBILDEN|Im2 LÄGGS PÅ NY PLATS:}

                  Image1.Canvas.CopyMode:= CopMod;

                  Image1.Canvas.CopyRect(CRd,Image2.Canvas,CRs);

                  MarkMove(0);

      {MarkMove(0)|AktiverarMouseMove via en DoNothing.

       Därmed uppdateras Färgrutan, samt övriga data

       som (ev.) finns på Im1 i anslutning till olika

       PekRörelser/Flytbilder.}

                  exit;

                end;{endIf Ctrl+Arrows}

 

med resultatet (skärmdump på texten ovan, sedan separat intag av RGB-palett och Tangent C som växlar till MoveAND):

 

 

Resultatet talar för sig självt: MoveAND låter oss se underlaget genom flytbildsobjektet i kombination med flytbildens pixels.

Trycker vi C igen återgår flytsättet till MoveCOPY:

 

 

 

Det finns (nu) EGENTLIGEN bara ett flytsätt kvar att beskriva — frånsett möjligheten att flytta objekten TONANDE genom varandra, vi kommer strax dit också: MoveMedSkipWHITE.

— En del (»elementära») ritprogram (Paint, Windows 7) kallar det flytsättet för »transparent», då det i själva verket »bara» betyder SKIPPA BAKGRUNDSFÄRGEN, mestadels vitt.

— När vi kopierar bildobjekt sker det ALLTYID via en omgivande begränsningsrektangel. Men den bildytan innehåller inte alltid heltäckande färger. Ofta använder vi stora bildytor med bara några få färger, typ cirklar, grafiska element generellt, som vi vill kunna passa in enbart på kurvformens figur. Det sättet kallas här generellt flytta med SkipWhite (eller annan bakgrundsfärg).

 

Omgående tangentrespons

 

För att få OMEDELBAR TANGENTRESPONS vid tryckning på tangent C — växlingen till nytt MoveSÄTT verkställs och syns omgående UTAN FLYTT — formulerar vi ett INTERNT MAKRO på UpdateMergeFlags sist (variablerna I: Integer; W: Word;):

 

  I:=ArrowStep;

  ArrowStep:=0;

  W:= VK_DOWN;

  FormKeyDown(Self,W,[ssCtrl]);

  ArrowStep:=I;

Förklaring:

— FÖRST spar vi undan vad aktuellt som finns i ArrowStep i I;

— Sedan simulerar vi en flytbildsflyttning via tangenterna Ctrl+PilNer (vilkensom) och vilken rutin finns på FormKeyDown:

— Genom att vi påtvingar ArrowStep=0 sker ingen bildflyttning, bara en kopiering i repris, men nu i aktuell form.

— Sist lämnar vi tillbaka lånet. Perfekt funktion.

 

 

HELP

Vänsterklick på den här introbilden öppnar en htm-fil (i datorns förinställda webbläsare) som beskriver programinnehållet, om ej redan bekant.

Ta bort den här introbilden genom att trycka på valfri tangent.:

 

— JäMFÖR MicrosoftSWEDEN:

DU TAR BORT DEN HÄR BILDEN GENOM ATT DU SÄTTER IGÅNG MED ATT BÖRJA TRYCKA PÅ VALFRI TANGENT.

— DU gör. DU tar. Och sen när DU har gjort det, KAN DU ta och göra det. Sen kan du göra det där andra också.

— Imperialismens Slavparadis på Jorden.

— MicrosoftSWEDEN (maktkåta översättarproffs) har möjligen aldrig reflekterat över att engelskans YOU i allmänhet i beskrivningar betyder det generaliserade MAN gör det och det, YOU do that and that, inte DU gör det och det. Det senare är OFÖRSKÄMT. Byt företag nu. Snälla.

— OM MAN INTE DIREKT har avancerat till FÖRSTÅENDE FÖRKLARANDE GUD, håller man sig städat och snyggt på nivån RekommenderaT, enligt erfarenhet: MAN kan göra si och så, och om det gäller att REALISERA det och det: man trycker först på den och sedan den, sedan kan man fortsätta ... . DU är reserverat för PERSONEN, det personliga valet, och det har ingen SOM INTE ÄR INBJUDEN med att göra.

 

 

Elementär flytbildsteknik — grundexempel i DELPHI4

 

MoveSkipWHITE

— Dramatiskt:

— Ett AccessViolationFEL envisades tills nyligen att återkomma — till synes kaotiskt — på MoveSkipWHITE-proceduren.

— Upprepade observationer visade strax:

— AcVi-avbrottet uppkommer om, och endast då, intagsbilden är större än ELLER LIKA MED bildskärmsbilden (Screen.Width resp. Screen.Height).

— När en extra  marginal på minus en pixel lades till i ScanLine-blocket, upphörde felet.

— Funktionen MoveSkipWhite har nyligen testats med intag av STORA bilder (från digitalkamera) och fungerar utan avbrott.

— Notera dock att STORA bilder med MoveSkipWhite tar MÄRKBART lång tid: flytbilden kräver för varje ny position runt 1/2 sekund för att uppdateras.

 

BaraFörVITT

I föregående kod

 

{FLYTBILDEN|Im2 LÄGGS PÅ NY PLATS:}

                  Image1.Canvas.CopyMode:= CopMod;

                  Image1.Canvas.CopyRect(CRd,Image2.Canvas,CRs);

 

 

finns bara en enda rad vi behöver koncentrera oss på för att förverkliga MoveSkipWHITE: den sista ovan.

   Hur görs det?

   Vi ska utforma en separat BitMap (B), lägga flytbilden Im2 på denna, tilldela B egenskapen Transparent=True, anställa vilken TransparentFärgen ska vara, och sedan helt enkelt använda Image1.Canvas.Draw(X0,Y0,B) direkt istället för ovanstående CopyRect:

 

if{(CopMod=cmSrcCopy)and}(SkipWhite=-1)then begin

B:= TBitMap.Create;

try

  B.Assign(Image2.Picture);

  B.Transparent:= True;

  B.TransparentColor:= clWhite;

  Image1.Canvas.Draw(X0,Y0,B);

finally

  B.Free;

end;

end else

Image1.Canvas.CopyRect(CRd,Image2.Canvas,CRs);

 

 

Med CopMod-parentesen:

BARA då MoveCOPY gäller får SkipWHITE mening:

— I flytläge MoveAND har SkipWHITE ingen innebörd — om vi ska vara konsekventa mot AND.

Utan CopMod-parentesen:

SkipWHITE ignorerar MoveAND:

— I flytläge överrider SkipWHITE tillfälligt ett MoveAND med MoveCOPY.

— Detta senare alternativ är EGENTLIGEN att föredra [ofta förekommande rutiner, man slipper trycka på två tangenter för att få SkipWhite från ett MoveAND] då SkipWHITE-funktionen (min erfarenhet) är den oftast förekommande framför MoveAND.

 

 

Vi sätter bara in koden ovan omedelbart efter föregående

                  Image1.Canvas.CopyMode:= CopMod;

— B finns redan deklarerad från tidigare i FormKeyDown:

 

 

MoveCOPY ovan: Hela intagsrektangeln med den vita ytan täcker för underlaget.

— Vi trycker nu på W = SkipWhite:

 

FörGrund¦BakGrund, FärgDisplay

 

Jag har här passat på att lägga till 2 ytterligare bottenpanelerVänster:

— Panel9(störreVita=Bakgrundsfärg) och Panel10(lillaSvartaMitten=Förgrundsfärg):

— Tangenterna BN sätter Bakgrundsfärg och FörgruNdsfärg respektive som finns just då under Peken.

— DelphiKODen är på FormkeyDown, caseKeyBlocket, variabeln D: TPoint; tillagd lokalt i FormKeyDown och globalerna fgCol,bgCol: TColor; längst upp i Unit efter UsesBlocket:

 

{SÄTT FÄRG — bAKGRUND FÖRGRUnD;}

{NoShift|BakgrundsFärg|B|Förgrund|N:}

      Ord('B'),Ord('N'):

                begin

                  GetCursorPos(D);

                  D:= Image1.ScreenToClient(D);

                  if not PtInRect(Image1.ClientRect,D) then exit;

                  case Key of

      Ord('B'):   bgCol:= Image1.Canvas.Pixels[D.X,D.Y];

      Ord('N'):   fgCol:= Image1.Canvas.Pixels[D.X,D.Y];

                  end;

                  Panel9.Color:= bgCol;

                  Panel10.Color:= fgCol;

                  UpdateMergeFlags;

                end;{endBN}

 

Voila.

— Ctrl+Pilar får nu flytbilden att åka över bildytan med den omgivande vita intagsrektangeln eliminerad: bara BildFiguren framträder.

 

BGOF, Begin

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Komplikationer i DELPHI(4) — BitMapTransparensen »Jävlas»

— Men håll ut: Befrielsen är nära.

 

SkipWHITE blocket ovan fungerar utmärkt med ”B.TransparentColor:= clWhite;”. Försöker man, emellertid, med andra bakgrundsfärger uppkommer (stundtals) rena snurrren: DELPHI4 förvandlas (ibland, ibland inte, på sätt som verkar helt oförutsägbara) till en vildhäst med fruktansvärda krafter. Med olika kodförsök ser det ibland ut som att en lösning är i antågande. Just närman TROR att man kan pusta ut, raseras snabbt hela arbetet till i stort sett ett osynligt dammoln, bara med en enda verkställande tangenttryckning: inget händer. Inte ett liv.

   Test med typen

 

with Image2.Picture.BitMap do begin

PixelFormat:= pf32Bit;

Transparent:= True;

TransparentColor:= bgCol;

Image1.Canvas.Draw(X0,Y0,Image2.Picture.BitMap);

end;{notOK|IngetHänder}

 

kan köras utan några som helst problem. Men inget händer: Den valda bakgrundsfärgen försvinner inte när man trycker W — om den inte är VIT förstås. Då går det. Inte annars. Flytbilden svarar helt enkelt inte på ovanstående allmänna transparenskommando.

   Inte heller den till synes mera preciserade typen

 

if{(CopMod=cmSrcCopy)and}(SkipWhite=-1)then begin

B:= TBitMap.Create;

  iW:= Image2.Width;

  iH:= Image2.Height;

R:= Rect(0,0,iW,iH);

try

  Image2.Picture.BitMap.PixelFormat:= pf32bit;

  B.PixelFormat:= pf32bit;

  BitMapRect(R,B);

  with B.Canvas do begin

   Brush.Color:= bgCol;

   FillRect(R);

  end;

  B.Assign(Image2.Picture);

  B.Transparent:= True;

  B.TransparentColor:= bgCol;

  Image1.Canvas.Draw(X0,Y0,B);

finally

  B.Free;

end;

end else

Image1.Canvas.CopyRect(CRd,Image2.Canvas,CRs);

 

visar livstecken, utom på vitt.

— Vi (min erfarenhet) vet redan i DELPHI4 att en TBitMap INTE svarar på typ Transparent=True om INGEN OPERATION ÄNNU HAR UTFÖRTS PÅ bildens minnesyta. Heldött. Går inte.

— Ovanstående försök innefattar emellertid just ett sådant klargörande: ytfyllnad med färg, samt särskild rutin för bildmått, säkerställer ATT TBitMap:en ska fungera.

   Likväl. Intet. Sten dött i Berget.

BakgrundsOberoendeFlytbild, BGOFbegin

Allafärger

Lösningen

Lösningen är av typen radikal, vi tar hela blocket för exakt jämförelse:

 

if{(CopMod=cmSrcCopy)and}(SkipWhite=-1)then

begin

B:= TBitMap.Create;

  iW:= Image2.Width;

  iH:= Image2.Height;

  zW:=0; zH:=0;

  if iW >= Screen.Width  then zW:=1;

  if iH >= Screen.Height then zH:=1;

R:= Rect(0,0,iW,iH);

try

  Image2.Picture.BitMap.PixelFormat:= pf32bit;

  B.PixelFormat:= pf32bit;

  B.Assign(Image2.Picture);

  B.Transparent:= True;

  B.TransparentColor:= bgCol;

  B.Canvas.Brush.Color:= bgCol;

  B.Canvas.FillRect(R);

 

  bR:= GetRValue(bgCol);

  bG:= GetGValue(bgCol);

  bB:= GetBValue(bgCol);

 

  for y:= 0 to iH-1-zH do begin

    Pa:= Image2.Picture.BitMap.ScanLine[y];

    Pb:= B.ScanLine[y];

    for x:= 0 to iW-1-zW do begin

  {IGNOREbgCol:}

     if (bR=Pa[4*x+2])and(bG=Pa[4*x+1])and(bB=Pa[4*x+0])then Continue;

  {FörÖverALLT från Im2 till B utom bgCol:}

     Pb[4*x+2]:= Pa[4*x+2];

     Pb[4*x+1]:= Pa[4*x+1];

     Pb[4*x+0]:= Pa[4*x+0];

    end;{endForX}

  end;{endForY}

 

  Image1.Canvas.Draw(X0,Y0,B);

finally

  B.Free;

end;

end else

Image1.Canvas.CopyRect(CRd,Image2.Canvas,CRs);

 

20Sep2014: Utan tillägget med zW och zH uppkommer ett AccessViolation = funktionen kapas = avbryts då och endast då intagsbilden är större än eller lika med bildskärmsbilden.

 

B.PixelFormat kan undvaras utan bieffekter, enligt test:

— Däremot om PixelFormat för Image2.PictureBitMap bockas för, uppkommer vid första nedtryckningen tangent W TOM FLYTBILD: den bara försvinner, och återkommer sedan utan vidare avbrott med bildflytten via Ctrl+Pilar.

ScanLineOperationer i allmänhet tillhör kategorin maximalt snabbgående, även för STORA bilder om matematiken i ScanBlocken inte är allt för omfattande: i 3D- och animeringsprogram är den just det — enorma ServerLandskap krävs, miljondatorer, för att bearbeta varje bildpixels slutdata. Här är vi mera blygsamma.

 

— PASSA HÄR GÄRNA PÅ att KOLLA HUR DELPHI4 visar information i typen Komplicerat programfel genom följande ändring i koden ovan:

 

— Ersätt iH i forYloopen med iW och iW med iH i forXloopen:

— Ctrl+F9 sker utan protester, P2 startar som vanligt med F9. Men, sedan vi importerat något (Ctrl+V) och trycker W i det startade programmet, sker avbrott med ett meddelande över nära hela bildskärmen:

 

Error

Project P2.exe raised exception class EAccessViolation with message 'Access violation at address 004428BB in module 'P2.exe.' Read of address 01E8F832'. Process stopped. Use Step or Run to continue.”.

 

— Tryck OK och sedan Ctrl+F2 för att avsluta P2 och återgå till Kodfönstret.

Ovanstående typFELmeddelande visar sig UTESLUTANDE ALLTID när man missar kod i samband med TBitMaps-rutiner eller gör slarvfel, som i ovanstående medvetet iscensatta exempel — ALLTID i samband med minneshanteringsrutiner. Ytterst svåra »kompileringsfel» att hitta och åtgärda om man som här INTE REDAN VET HUVUDORSAKEN. Ha det gärna i bakhuvudet för vidare. Fel gör vi alla, förr eller senare. (Ju grundligare, desto bättre, förutsatt VILJA att komma igen).

BakgrundsOberoende flytbild, exempel

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Galant. Befriande. Grymt snabbt — förutsatt intagna bilder är mindre än bildskärmen: ju mindre desto snabbare. Test på Intagna bilder från digitalkamera (flera gånger större än en 23 tums bildskärm) visar att MoveSkipWHITE kräver runt 1/2 sekund för att uppdatera flytbilden. Perfekt funktion.

 

Verifierande test

 

Nedan Vänster: TestBild. Mitten: Efter Import Ctrl+V till P2 och Fönsteranpassning F5. Höger: Efter ytterligare Ctrl+V — vi använder en kopia av underlaget som flytbild och lämplig passning för kontroll:

— MoveCOPY med IncludeWHITE som standard för att se intagsrektanglarna i flytbilderna från start:

 

 

Nedan Vänster: Efter W=SkipWHITE. Mitten: Efter B=bgCol med Peken över gråytan. Höger: Efter B=bgCol med Peken över svartytan.

 

 

Perfekt. Exakt som vi ville ha det.

— Nu framträder även vit text (som skapats på given homogen färgyta) i flytbilderna och som obehindrat kan flyttas över till andra godtyckliga bildytor, synligt(med bakgrunden) eller osynligt(utan bakgrunden), tangent W växlar.

— Observera här (återigen, för den som bara ser den här presentationen): alla ändringar i flytbildssätten framträder omedelbart visuellt med en enda enkel tangentnedtryckning: W C B N. Inget musklickande. Inget armvevande över halva bildskärmen för att hitta. Inget letande efter menyer och ToolBars. Lugnt. Ingen stress.

 

 

20Okt2014 — Mera TransparensenJävlasProblem:

— Men LÖSNINGEN ovan (BGOF) grusades snart med följande upptäckt:

— Perfekt funktion — tills plötsligt (och turligt för upptäcktens del) ett bildmått 388;256 kom med i bilden (även 2·388×256 ger AcVi-avbrott):

— AccessViolationAVBROTT inträder när SkipWhite-funktionen aktiveras.

  LÖSNINGEn — vi gör oss oberoende sv ScanLine-funktionen genom att läsa direkt från och skriva direkt till bildens dataminne:

 

{ENDA FUNGERANDE HELHETSLÖSNINGEN:

—388;256-felet, och även >Screen-Felet eliminerat som det ser ut|20Okt2014:}

Procedure TmMoveSkipWHITE;

var

  A,B:           TBitMap;

  Pa,Pb,aP,bP:   PChar;

  TMa,TMb:       TMemoryStream;

  W,H,x:         Integer;

  R:             TRect;

  aR,aG,aB:      Byte;

begin with Form1 do begin

          TMa:= TMemoryStream.Create;

          TMb:= TMemoryStream.Create;

          A:= TBitMap.Create;

          B:= TBitMap.Create;

          W:= Image2.Width;

          H:= Image2.Height;

          R:= Rect(0,0,W,H);

{Tar ut bakgrunden för jämförelse:}

          aR:= GetRValue(bgCol);

          aG:= GetGValue(bgCol);

          aB:= GetBValue(bgCol);

       try

{SpecialRutin, etablerar bitmap:ens dimensioner:}

          BitmapRect(R,A);

          BitmapRect(R,B);

          A.Canvas.Brush.Color:= clWhite;

          A.Canvas.FillRect(R);

{Preparera|BehandlingsBitMaps:}

          A.PixelFormat:= pf32bit;

          B.PixelFormat:= pf32bit;

{FLYTBILD=Källbild|Im2¦Copy|Im1¦MarkRect|TillA|}

          A.Canvas.CopyRect(R,Image2.Canvas,R);

{PREPARERA MÅLBILDENS BITMAP FÖR BAKGRUNDSELIMINERING:}

          B.Canvas.Brush.Color:= bgCol;

          B.Canvas.FillRect(R);

          B.TransparentColor:= bgCol;

          B.Transparent:= True;

{SPARA TILL MemoryStreamen så att vi kan göra ändringar därifrån:}

          A.SaveToStream(TMa); //Källbilden|FlytBildeIm2.

          B.SaveToStream(TMb); //Målbilden|SkipBackGroundColorResult.

{TILLDELA MemoryStreamen en AdressPekare - vårt HuvudTransportMedel i ändringarna:}

          Pa:= TMa.Memory;

          Pb:= TMb.Memory;

{Samma som hela BMP-strukturen|Med BitMapInfoHeader: börjar från pos54:}

{En enda lång sammanhängande DataMinnesAdressRad för hela bilden:}

             for x:= 0 to H*W - 1 do begin

                bP:= Pb + 54 + 4*x;

                aP:= Pa + 54 + 4*x;

{SkipBgCOL:}

                if (aR=Byte((aP +2)^))

                and(aG=Byte((aP +1)^))

                and(aB=Byte((aP +0)^))

                then Continue;

{BG-ytan kvarlämnas orörd på B för slutlig transparens via Im1Draw:}

                Byte((bP +2)^):= Byte((aP +2)^);

                Byte((bP +1)^):= Byte((aP +1)^);

                Byte((bP +0)^):= Byte((aP +0)^);

 

             end;{endForX}

{FINALIZING:}

{UPPDATERA ÄNDRINGARNA TILL den ursprungliga bitmap:en|B:}

{Förbered MemoryTillBitMap:}

{Börjar från MinnesPekarensPosition - funkar inte om annat än från 0:}

          TMb.Position:= 0;

{UPPDATERAR ÄNDRINGARNA:}

          B.LoadFromStream(TMb);

{FlytbildsPreparering|OK|Bilden ritas ut|X0|Y0 flytbildsparametrar:}

          Image1.Canvas.Draw(X0,Y0,B);

       finally

         A.Free;

         B.Free;

         TMa.Free;

         TMb.Free;

       end;

end; {endWithForm1}

end; {endTmMoveSkipWHITE}

{Överflyttad kopia från T2014|20Okt2014.}

 

 

Med denna justering har ytterligare fel ännu inte observerats

— För vidare observation (20Okt2014).

   Kommentar allmänt DELPHI4 ScanLines:

— Något är alldeles tydligt uppenbart fel — antingen i DELPHI4 eller på annat sätt i förening med SAcanLine-funktionen (subrutin) som under speciellt taskiga lägen åstadkommer försmädliga AccessViolationAvbrott — i sig inte farliga, men tillräckliga för att den egentliga funktionen hoppas över. Vi har nu SÄKERT studerat TRE ScanLineFELområden: 16;64-felet, 388;256-felet och StörreÄnScreen-felet.

— Samtliga dessa ScanLineFEL försvinner (tydligren) om TMemoryStream-metoden används istället, vilket garanterar fullständigt ScanLineOberoende (med exakt 32-bitars minneshantering).

 

Invertera:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Invertera flytbilden — tangent I

Vi lägger till ytterligare en sådan enkel, elementär, flytbildsinstans: FormKeyDown CaseBlocket utan Shift, alla variabler finns redan:

 

 {INVERTERA FLYTBILDEN|11Sep2014:}

      Ord('I'): begin

                  with Image2.Canvas do begin

                   R:= Rect(0,0,Image2.Width,Image2.Height);

                   B:= TBitMap.Create;

                   try

                    BitMapRect(R,B);

                    B.Assign(Image2.Picture);

                    CopyMode:= cmDstInvert;

                    CopyRect(R,B.Canvas,R);

                   finally

                    B.Free;

                   end;

                   CopyMode:= cmSrcCopy;

                  end;{endWithIm2Canvas}

                  UpdateMergeFlags;

                end;

 

Checking: Vänster: Efter Ctrl+V och F5. Höger: Efter I:

 

 

Utomordentligt. Att Inverteringsfunktionen fungerar perfekt kontrollerar vi genom att lägga den inverterade kopian över originalet och köra MoveAND (Tangent C). Korrekt funktion (ickeINV + INV = helsvart) betyder att bilderna tar ut varandra med resultat i helsvart:

 

Vänster: Efter Ctrl+V No2 och Tangent C; helsvart. Höger: Ctrl+Numpad1(Step1p), Ctrl+ PilHö:

 

 

Vi ser att KONTURER BÖRJAR FRAMTRÄDA med minsta förskjutning på en pixel RightDown i leden XY mellan två varandra inverterade original.

— Det är också programgrunden till det mycket eftertraktade — och mycket effektiva fotoredigeringsverktyget/bildbehandlingsverktyget — SHARPENING generellt.

 

 

RGBpalett:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Enkel RGB-palett F4 med FärgUnderPeken — Numpad|0

 

Ofta, ibland, behöver vi få i varje fall ungefärliga färger som motsvarar NATRLIGA SPEKTRUMets färger:

 

 

Färgkartan ovan (från FinishingTouch Windows 95-eran) — orienterad vertikalt — finns inlagd som Palett3.bmp i projektkatalogen för P2.

 

Tangent F4 tar fram den på Image1 och lägger ut den som flytbild enligt DELPHI4-koden på FormKeyDown F4, CaseKeyBlocket:

 

 {PALETT RGBflytbild:}

      VK_F4:    begin

                  S:= 'Palett3.bmp';

                  if not FileExists(S) then exit;

                  Image2.Picture.LoadFromFile(S);

                  Image3.Picture.LoadFromFile(S);

                  {Anger bildmåttet, PanelLabeln överst i mitten:}

                  Panel4.Caption:=IntToStr(Image2.Width)

                  +';'+IntToStr(Image2.Height);

                  X0:=0; Y0:=0;

                  CRs:=Image2.ClientRect;

                  CRd:=CRs;

                  OffsetRect(CRd,X0,Y0);

                  Image3.BoundsRect:= Image2.BoundsRect;

                  Image3.Canvas.CopyRect(CRs,Image1.Canvas,CRd);

                  Image1.Canvas.CopyMode:= cmSrcCopy;

                  Image1.Canvas.CopyRect(CRd,Image2.Canvas,CRs);

                  SetCursorPos(Left+Panel1.Left+32, Top+Panel1.Top+Y0+26+4);

                  ClipBoardImported:= True;

                end;{endF4}

 

ClipBoardImported här inlagt om man vill optimera fönsterstorleken (F5) för detta speciella fall.

— Med F5 (P2-fönstret här roterat +90°) ger F4-kommandot Palett3 intagen med Peken förinställd på svart:

 

 

  

 

 

Fortsättningen i FÄRGANALYSATOR RGB|HSB OCH FÄRGREDIGERARE med DELPHI4.

 

VisuellaSpektrumPalettRitningen i DELPHI4 — Pixels-metoden

A,N,Z: Integer; Blocket nedan ger endast EN horisontell rad, denna har sedan dubblerats i höjd:

 

A:= 255;

Z:= 0;

with Image1.Canvas do

begin

for N:= 0 to 127 do Pixels[N+0*127,50]:= RGB(A,2*N,Z);

for N:= 0 to 127 do Pixels[N+1*127,50]:= RGB(A-2*N,A,Z);

for N:= 0 to 127 do Pixels[N+2*127,50]:= RGB(Z,A,2*N);

for N:= 0 to 127 do Pixels[N+3*127,50]:= RGB(Z,A-2*N,A);

for N:= 0 to 127 do Pixels[N+4*127,50]:= RGB(2*N,Z,A);

end;{endWithIm1}

Normal — också maximal färgmättnad

 

TONSEKTORERNA avgränsas och bestäms av ELEMENTARSPEKTRALFÄRGERNA resp

0|RÖD(255,0,0) 1|GUL(255,255,0) 2|GRÖN(0,255,0) 3|INDIGO(0,255,255) 4|BLÅ(0,0,255) 5|VIOLETT(255,0,255), sedan

åter mot 6|0|RÖD(255,0,0) — inte medtagen ovan: ingår inte i det visuella spektrumet:

 

 

För att få med även sista intervallet 5 som sluter spektrumcirkeln mot rött igen, ska det skrivas med B från 255 mot 0:  5: C:= RGB(A,Z,A-K*N);.

— Vi måste ha med detta sista intervall för att fullt kunna omvandla mellan RGB och HSB: H [eng. Hue, FärgTON eller FärgNYANS] i HSB är just ovanstående visuella spektrum.

 

VisuellaSpektrumPalettRitningen i DELPHI4 — SetPixel-metoden (10ggr snabbare)

H: THandle; A,N,Z,K,I: Integer; C: TColor; — K-faktorn bestämer TonSektorIntervallet, här förkortat till 51pixels:

— Programblocket nedan ger endast en horisontell pixelrad, denna sedan dubblerad i höjd:

 

H:= Image1.Canvas.Handle;

A:= 255;

Z:= 0;

C:= 0;

K:= 5;

I:= 255 div K;

with Image1.Canvas do

begin

 for TonSektor:= 0 to 4 do

  for N:= 0 to I do begin

   case TonSektor of

    0: C:= RGB(A,K*N,Z);

    1: C:= RGB(A-K*N,A,Z);

    2: C:= RGB(Z,A,K*N);

    3: C:= RGB(Z,A-K*N,A);

    4: C:= RGB(K*N,Z,A);

   end;

   SetPixel(H, N + TonSektor*I, 50, C);

  end;

end;{endWithIm1}

 

VisuellaSpektrumPalettRitningen i DELPHI4 — ScanLine-metoden (1000ggr snabbare)

B: TBitMap;  R: TRect;  Pb: PByteArray;  bR,bG,bB: Byte; K,A,Z,N,TonSektor,I,J: Integer; :

— Programblocket nedan ger hela bilden som ovan:

 

R:= Rect(0,0,300,10);

B:= TBitMap.Create;

try

 BitMapRect(R,B);

 B.PixelFormat:= pf32Bit;

 B.Canvas.Brush.Color:= clWhite;

 B.Canvas.FillRect(R);

       A:= 255;

       Z:= 0;

       K:= 5;

       I:= 255 div K;

       bR:=0; bG:=0; bB:=0;

 Pb:= B.ScanLine[0];

       for TonSektor:= 0 to 4 do

        for N:= 0 to I do begin

         J:= 4*(N + TonSektor*I);

         case TonSektor of

          0: begin bR:= A;     bG:= K*N;   bB:= Z;   end;

          1: begin bR:= A-K*N; bG:= A;     bB:= Z;   end;

          2: begin bR:= Z;     bG:= A;     bB:= K*N; end;

          3: begin bR:= Z;     bG:= A-K*N; bB:= A;   end;

          4: begin bR:= K*N;   bG:= Z;     bB:= A;   end;

         end;

         Pb[J + 2]:= bR;

         Pb[J + 1]:= bG;

         Pb[J + 0]:= bB;

        end;

 for I:= 0 to 20 do

 Image1.Canvas.Draw(0,I,B);

finally

 B.Free;

end;

 

Fortsätt i EditColors — färgredigering och analys RGB|HSB.

 

 

 

Fel1664

Elementär flytbildsteknik — grundexempel i DELPHI4

 

112;320-felet

16;64-felet — ScanLineFEL i DELPHI4

ScanLines

 

   B:= TBitMap.Create;

   try

     for W:= 16 to 200 do

     for H:= 16 to 200 do

     begin

       R:= Rect(0,0,W,H);

       BitMapRect(R,B);

       ClipBoard.Assign(B);

       D:= Ord('V');

       FormKeyDown(Self,D,[ssCtrl]);

       ClipBoard.AsText:= IntToStr(W)+';'+IntToStr(H);

       D:= Ord('R');

       FormKeyDown(Self,D,[]);

     end;

   finally

     B.Free;

   end;

 

AVBROTT sker för alla n heltalskombinationer n16;n64 eller n64;n16 som pixelmått på den källbild som ska vändas horisontellt eller roteras +90° OM ScanLine-funktionen i DELPHI4 används: första stannar på 16;64 med ett programexekveringsdavbrott av typen AccessViolation: funktionen har havererat.

— Används istället en TMemoryStream — direkt ByteÅtkomst i BitMapens Dataminne — ger ovanstående testgenomgång (33.856=184² stycken rektanglar testade) perfekt avbrottsfri körning. Tangenterna Ctrl+V tar in Urklippskopian, och R leder till rotationsblocket. Det faktum att TMemoryStream klarar biffen utan protester styrker misstanken (starkt) att:

32bitars rektangelvändning på ByteBaserad Horisontell — men inte vertikal — dataomkastning och överföring av bilddata från Längd till Bredd och vice versa INTE är korrekt utformat i DELPHI4. Det blir svårt att se saken på annat sätt med TMemoryStreamBeviset. Procedurerna följer nedan.

 

I samband med test av ovanstående (15Sep2014) — P2-fönstrets mått efter anpassning (F5) till den importerade Palett3-bilden — med import av det fönstret till T2014 och sedan FlipHorizontal och Rotate90, visas ACCESS VIOLATION:

— Har aldrig tidigare inträffat under de snart 15 år som programformen använts.

— Inspektion visade att det är bildmåtten som är kritiska:

— Skiljer det på bara en pixel, visas inte felet.

 

TBitMapInfoHeader:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Efter Inside WINDOWS FILE FORMATS s57, Tom Swan, Sams Publishing 1993

 

15-18 4             1.DWORD        biSize: ......................   Longint;

19-22 4             2.LONG            biWidth: ...................    Longint;

23-26 4             3.LONG            biHeight: ..................    Longint;

27-28 2             4.WORD           biPlanes: .................    Word;

29-30 2             5.WORD           biBitCount: ..............    Word;

31-34 4             6.DWORD        biCompression: ......     Longint;

35-38 4             7.DWORD        biSizeImage: ...........    Longint;

39-42 4             8.LONG            biXPelsPerMeter: ....   Longint;

43-46 4             9.LONG            biYPelsPerMeter: ....    Longint;

47-50 4             10.DWORD      biClrUsed: ................   Longint;

51-54 4             11.DWORD      biClrImportant: ........   Longint;

 

RGB-formatets datalängd — formen oven samma som via DELPHI4:s TMemoryStream.

Pixeldatats offsetadress är 54. DataPekaren ska ställas på P + 54 för att få bildens första pixel (B-värdet i första färggruppen BGR#).

 

FlipHorizontal:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Proceduren nedan testad OK 15|16Sep2014 — FlipHorizontal:

 

Procedure TMFlipHorizontal(SourceIm: TImage);

var

  A,B:           TBitMap;

  Pa,Pb,iP,P:    PChar;

  TMa,TMb:       TMemoryStream;

  W,H,x,y,Sx,Ex: Integer;

begin with Form1 do begin

  TMa:= TMemoryStream.Create;

  TMb:= TMemoryStream.Create;

  A:= TBitMap.Create;

  B:= TBitMap.Create;

  try

   {SpecialRutin, etablerar bitmap:ens dimensioner:}

    BitmapRect(CRs,A);

    BitmapRect(CRs,B);

{Källbilden|Im2¦Copy|Im1¦MarkRect|TillA|CRd|s|Avgörande:}

    A.Canvas.CopyRect(CRd,SourceIm.Canvas,CRs);

{Preparera|BehandlingsBitMaps:}

    H:= A.Height;

    W:= A.Width;

    A.PixelFormat:= pf32bit;

    B.PixelFormat:= pf32bit;

    B.Canvas.Brush.Color:= clWhite;

    B.Canvas.FillRect(CRs);

{SPARA TILL MemoryStreamen så att vi kan göra ändringar därifrån:}

    A.SaveToStream(TMa);

    B.SaveToStream(TMb);

{TILLDELA MemoryStreamen en AdressPekare - vårt HuvudTransportMedel i ändringarna:}

    Pa:= TMa.Memory;

    Pb:= TMb.Memory;

{Samma som hela BMP-strukturen|Med BitMapInfoHeader: börjar från pos54:}

    for y:= 0 to H-1 do begin

     Sx:= (H-1-y)*W;

     Ex:= (H - y)*W - 1;

     for x:= Sx to Ex do begin

      iP:= Pb + 54 + 4*(Ex + Sx - x);

       P:= Pa + 54 + 4*x;

      Byte((iP +2)^):= Byte((P +2)^);

      Byte((iP +1)^):= Byte((P +1)^);

      Byte((iP +0)^):= Byte((P +0)^);

     end;{endForX}

    end;{endForY}

{FINALIZING:}

   {UPPDATERA ÄNDRINGARNA TILL den ursprungliga bitmap:en|B:}

   {Börjar från MinnesPekarensPosition - funkar inte om annat än från 0:}

    //TMa.Position:= 0|Behövs inte|InteÄndrad.

    TMb.Position:= 0;

{UPPDATERAR ÄNDRINGARNA:}

    B.LoadFromStream(TMb);

{FlytbildsPreparering|OK|Bilden ritas ut:}

    Image1.Canvas.CopyMode:= cmSrcCopy;

    BitmapToIm(B);

    //Image1.Canvas.Draw(X0,Y0,B);

  finally

    A.Free;

    B.Free;

    TMa.Free;

    TMb.Free;

  end;

end;{endWithForm1}

end;{endTMFlipHorizontal}

 

 

Proceduren nedan testad OK 15|16Sep2014 — RgB till BgR:

 

ExchangeRgB:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

RGB till BGR:

 

{Färgvändningen|BitMap A|RGB till BGR:}

{Samma som ovan men enbart med BitMap A och ByteKoden:}

R:= Byte((aP +2)^);

Byte((aP +2)^):= Byte((aP +0)^);

Byte((aP +0)^):= R;

 

TestatOK 16Sep2014. Bägge procedurerna fungerar ännu så länge utan observerade fel.

 

NEJ. NYLIGEN ÄNNU ETT AVBROTT. FlipHorizontal.

— Nej. Berodde på att jag hade satt

 

    H:= SourceIm.Height;

    W:= SourceIm.Width;

 

istället för korrekta

 

    H:= A.Height;

    W:= A.Width;

 

EFTERSOM SourceIm i fallet MarkRect är Image1 (kopiering sker från större till mindre):

— Avbrott med MarkRect och sedan direkt H, medan en kopia som går till Image2 inte gav avbrott.

— Ordnat, således. DELPHI4-dramatik.

 

— Märkvärdigt är det. Testade nyligen återigen Rot90° på »gamla ScanLineBlocket» Unit1 T2014:

— Nu uppför sig den delen ytterligare rebelliskt: för varje rotation minskas originalbildens bild, inte bildytan, med 1 pixelrad, så att det som blir kvar minskar med antalet rotationer.

— Det var något nytt. Har aldrig tidigare visat sig.

Mitt fel: R:= Bounds(0,0,CRd.Bottom+1,CRd.Right+1); REST efter nyligen genomförda TEST.

— Tas tillägget bort fungerar det som tidigare, frånsett 16;64-felen.

— Rättat med hjälp av gamla Project2002.

   DELRESULTAT AV FELSÖKNINGEN 16;64-felet:

   EFTERSOM TMemoryStream INTE visar något fel på 112;320-Fönstret från P2, men att ScanLineBlocket gör det, UPPSTÅR MISSTANKEN att 16;64-felet ligger hos DELPHI4 i ScanLine-algoritmen.

— Nästa steg blir att försöka utforma en TMemoryStreamProcedur för Rot90°-fallet också. Det kommer att avgöra.

 

TMrot90:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Proceduren nedan testad OK 15|16Sep2014 — Rotate90°:

 

Procedure TMScanRot(SourceIm: TImage);

var

  A,B:           TBitMap;

  R:             TRect;

  P,iP,Pa,Pb,

  TMa,TMb:       TMemoryStream;

  W,H,x,y,Sx,Ex,

  iX:            Integer;

begin with Form1 do begin

  TMa:= TMemoryStream.Create;

  TMb:= TMemoryStream.Create;

  A:= TBitMap.Create;

  B:= TBitMap.Create;

  try

{Målbildens roterade källrektangel|Width¦Height¦omvända|Rect eller Bounds här egalt:}

    R:= Bounds(0,0,CRd.Bottom,CRd.Right);

   {SpecialRutin, etablerar bitmap:ens dimensioner:}

    BitmapRect(CRs,A);

    BitmapRect(R,  B);

{Källbilden|Im2¦Copy|Im1¦MarkRect|TillA|CRd|s|Avgörande:}

    A.Canvas.CopyRect(CRd,SourceIm.Canvas,CRs);

{Preparera|BehandlingsBitMaps:}

    H:= A.Height;

    W:= A.Width;

    A.PixelFormat:= pf32bit;

    B.PixelFormat:= pf32bit;

    B.Canvas.Brush.Color:= clWhite;

    B.Canvas.FillRect(CRs);

{SPARA TILL MemoryStreamen så att vi kan göra ändringar därifrån:}

    A.SaveToStream(TMa);

    B.SaveToStream(TMb);

{TILLDELA MemoryStreamen en AdressPekare - vårt HuvudTransportMedel i ändringarna:}

    Pa:= TMa.Memory;

    Pb:= TMb.Memory;

{Samma som hela BMP-strukturen|Med BitMapInfoHeader: börjar från pos54:}

{Överföringen från A till B|Sx = WH - W - Wy| Ex = WH - 1 - Wy|iX=x-Sx= 0 1 2 3 .. :}

    for y:= 0 to H-1 do begin

      Sx:=(H-1-y)*W;

      Ex:= Sx + W-1;

      for x:= Sx to Ex do begin

       iP:= Pb+54 + 4*(y + H*(x-Sx));

        P:= Pa+54 + 4*x;

       Byte((iP +2)^):= Byte((P +2)^);

       Byte((iP +1)^):= Byte((P +1)^);

       Byte((iP +0)^):= Byte((P +0)^);

     end;{endForX}

    end;{endForY}

{FINALIZING:}

   {UPPDATERA ÄNDRINGARNA TILL den ursprungliga bitmap:en|B:}

   {Börjar från MinnesPekarensPosition - funkar inte om annat än från 0:}

    TMb.Position:= 0;

{UPPDATERAR ÄNDRINGARNA:}

    B.LoadFromStream(TMb);

{FlytbildsPreparering|OK|Bilden ritas ut|S|GlobalSträng|SpeciellSluthantering:}

    S:='ScanRotCompleted';

    BitmapToIm(B);

    //Image1.Canvas.Draw(X0,Y0,B);

  finally

    A.Free;

    B.Free;

    TMa.Free;

    TMb.Free;

  end;

end;{endWithForm1}

end;{endTMScanRot|16Sep2014.}

 

 

Ex = Sx + W–1 = (H-1-y)*W + W–1 = WH-W-Wy  + W–1 = WH-Wy –1 = W(H-y) –1

 

Enda som skiljer FlipHorizontal från Rotate90° i DataLoopen är

FH    iP:= Pb + 54 + 4*(Ex + Sx - x);

R90   iP:= Pb + 54 + 4*(y + H*(x-Sx));

 

Råformen i 90°-rotationerna är

 

          Byte((Pb+54+(4*y)+ 4*(iX)*H +2)^):= Byte((Pa+54+ 4*x+2)^);

          Byte((Pb+54+(4*y)+ 4*(iX)*H +1)^):= Byte((Pa+54+ 4*x+1)^);

          Byte((Pb+54+(4*y)+ 4*(iX)*H +0)^):= Byte((Pa+54+ 4*x+0)^);

med

iX = x – Sx = x – W(H–1–y);

Pb+54+(4*y)+ 4*(iX)*H

kan då förenklas via

Pb+54+ 4*(y+ H*iX) = Pb+54+ 4*(y+H*(x–Sx)) = iP;

 

— Hur gick det, då, med 112;320-fönstret?

 

 

Perfekt.

— En säker TESTFORM som bevisar att 90°-rotationerna fungerar perfekt är att ta ut en himmelsdel på ett foto och rotera 4 ggr:

 

 

Efter fjärde 90°-rotationen ska uttaget smälta in tillbaka på exakt plats det togs ut ifrån — och »utan förluster», dvs., inga borttagna kantlinjer (eller annat) får förekomma. Bilden ovan efter test av föregående TMScanRot.

 

— Det skulle, då, betyda: ScanLine-funktionen i DELPHI4 är inte korrekt utformad.

— Det är heller ingen avundsvärd programuppgift att försöka göra en KOMMERSIELL programprodukt som ska täcka samtliga möjliga PixelFormat-fall (man behöver nog avancera till närmast GUD för den uppgiften);

— En öppen svårighet — och som visat sig så svår att ens få visuell koll på (nu först efter 15 år[!]) — KAN just vara BILDREKTANGELOMVÄNDNINGAR kontra den YTTERST känsliga minneshanteringsalgoritmen: missas en enda BIT eller Byte är det KÖRT: Access Violation @Address ... . Säkert som amen i kyrkan.

— ScanLine i DELPHI4 FUNGERAR FÖR ÖVRIGT PERFEKT

— om inga andra Det-Tar-Runt-15år-Att-Upptäcka-Felen-Övningar är att vänta.

   Så länge man inte laborerar med VÄNDNING av bildrektanglarna — FlipHorizontal Rotera90°: FlipVertical lider inte av 16;64-felet — verkar allt fungera utan några som helst problem: inga observerade avbrott (än).

 

 

 

Separat test med rektanglar från 16×16p upp till 200×200p gjordes nyligen (Speciell TestLoop 16Sep2014|T2014 33856st Rect) på TMScanRot: helt galant felfritt. Det styrker bevisningen.

 

   B:= TBitMap.Create;

   try

     for W:= 16 to 200 do

     for H:= 16 to 200 do

     begin

       R:= Rect(0,0,W,H);

       BitMapRect(R,B);

       ClipBoard.Assign(B);

       D:= Ord('V');

       FormKeyDown(Self,D,[ssCtrl]);

       ClipBoard.AsText:= IntToStr(W)+';'+IntToStr(H);

       D:= Ord('R');

       FormKeyDown(Self,D,[]);

     end;

   finally

     B.Free;

   end;

ClipBoardKopian för W;H ifall avbrott skulle ske (vetskap om var). Här: NoProblemo.

 

 

 

 

EditColors

Senast vald Bakgrund(B)|Förgrund(N) redigeras — sliderna 1. dras med musen, 2. flyttas med PilVäHö Ctrl+ NumPad|123 sätter 1 5 20 steg, 3. numeriskt med Alt+nnn; PilUppNer Radval; CapsLock Kolumnval RGB|HSB, markering visar parameter; Enter Verkställer, Esc ångrar&avslutar, R åter utgångsläget.

 

 

 

EditColors:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

FÄRGANALYSATOR RGB|HSB

med FÄRGREDIGERARE i DELPHI4

Panel12|Image5

 

 

 

 

·          MusVäNER på aktuell knapp|slid ger skjutreglageeffekt

·          Alt+ nnn med siffror nnn på sifferbordet  NumPad|0-9 skriver in värdena direkt på vald post (markerat som ovan, himmelsblå bakgrund)

·          Piltangenter VäHö steppar (flyttar alla RGB-slider om HSB är valt) i steg om 1 5 eller 20 pixels med inställning Ctrl+ NumPad|1 2 3

·          Piltangenter UppNer växlar rad R(H)G(S)B(B), CapsLock växlar kolumn RGB eller HSB

·          Enter sätter senast vald färg fgCol FÖRGUND eller bgCol BAKGRUND; Esc avslutar utan ändring (Space+Enter öppnar)

·          Tanget O = Enter = SättNy; Tangent C = Escape = Exit = AvslutaUtanÅtgärd; Tangent R = TaOmRedigeringenFrånInslagspunkten.

·          EditColorsPanelen visas längst ner till höger i P2:

·          RedigeraFärgen är den som SIST valdes av fgCol=Förgrundsfärgen=LillaRutanNedreVä Tangent N eller bgCol=Bakgrundsfärgen=StoraRutanUnder Tangent B (närmsta tangenten Bakom N)

 

 

 

Ett mer eller mindre OUNDGÄNGLIGT bildhanteringsverktyg är tillgång till FÄRG + detaljerad färgförklaring:

— Det innebär att man alltid i alla lägen har tillgång till

 

·         en FÄRGANALYSATOR — enkelt elementär inblick i spektralmatematiken (HSB) tillsammans med RGB-värden

·         en FÄRGREDIGERARE integrerad för att PÅ ENKLASTE SÄTTET få fram exakt önskad färg (bakgrund eller förgrund) med numeriska värden, om så önskas

 

DELPHI4kod:

1. Unit1C, ny — EditColorsUnit

2. uses Unit1C, tillägg till usesBlocket Unit1

3. Panel12 och Image5|alClient|Visible|AutoSize=False: Unit1; ecTimer: deklareras på Unit1C efter usesBlocket enligt

 

type

  TecTimer = class(TTimer)

  Procedure OnEditColors(Sender: TObject);

  end;

 

och som skrivs (vidare nedan) i ImplementationBlocket Unit1C på det (notera) speciella sättet

 

Procedure TecTimer.OnEditColors(Sender: TObject);

...

(och Vilket PunktPåt Garanterar att nybörjaren har det JÄTTESVÅRT med Delphi[4] de första 50 åren ...: i princip OMÖJLIGT att »räkna ut logiskt» på förhand de olika sätten: man måste ha detaljerad inblick i Delphis/Pascals type-class-system).

 

och som deklareras GlobalVariabel i Unit1C i varIABELblocket efter usesBlocket

 

       ecTimer:     TecTimer;

 

ecTimer (EditColorsTimer) skapas separat Unit1 på FormCreate (sist) enligt

 

       ecTimer:= TecTimer.Create(nil);

       with ecTimer do begin

       Enabled:= False;

       OnTimer:= OnEditColors;

       end;

(nil [”ingenting”] anger att ecTimer saknar Parent, annars ska ParentEgenskapen stå i parentesen, typ ”Form1”; nil används generellt för att säkra att en variabel INTE upptar någon direkt plats i datorminnet, typ [innan ..Create] BitMap1:= nil;.

— Delphihjälpen [Overview of pointers] skriver på nil:

”The reserved word nil is a special constant that can be assigned to any pointer. When nil is assigned to a pointer, the pointer doesn’t reference anything.”)

 

och entledigas från DatorMinnet på Unit1 FormClose enligt

 

           ecTimer.Free;

 

Allt det övriga finns i Unit1C med procedurerna i typeBlocket

 

  Procedure vRGBtoHSB(var C1,C2,C3: Integer);

  Procedure vHSBtoRGB(var C1,C2,C3: Integer);

  Procedure EditColors(var Key: Word; Shift: TShiftState);

 

och sedan deras ordinarie kodblock i Implementationsdelen, tillsammans med den nu särskilt originellt, till skillnad från de andra, angivna TecTimer.OnEditColors (först i kön):

— Proceduren nedan  TecTimer.OnEditColors är INTE deklarerad globalt i Unit1C:

— Vi gör så ibland — skriver LOKALA procedurer närmast ÖVER en undre MasteProcedur (alternativt, sätter in den som en INRE NÄSTAD procedur i mastern direkt efter varBlocket): Mastern kan använda en icke globalDeklarerad procedure OM, och endast då, denna står FÖRE i aktuell Unit. Står den efter, känns den inte igen.

 

{EditColorscTimer|Används för att simulera MouseMove|RGB|HSB-sliderna på Image5:}

Procedure TecTimer.OnEditColors(Sender: TObject);

var

  W: Word;

begin with Form1 do begin

  if not Panel12.Visible then exit;

  if GetKeyState(VK_LBUTTON)<=-127 then

  begin

    ecTimer.Interval:= 10;

    W:= Ord(#2);

    EditColors(W,[]);

    exit;

  end

  else

  begin

{STANDby:}

    ecTimerON:=False;

    ecTimer.Interval:= 100;

{RENSA Alt+NumPad0..9 Input om Ångra före 3 inslag:}

    if (GetKeyState(VK_MENU)>-127)

    and(Length(S)<3)

    and(KeyNP09)

    then

    begin

      S:= '';

      KeyNP09:=False;

      Label1.Caption:= 'Clear';

    end;{endIfÅngraInslagFöre3}

  end;{endEcTimerStandBy}

end;{endWithForm1}

end;{endTForm1ecTimerTimer|14Jul2014 Uni5 T2014|17Sep2014|Uni1C|P2}

{ANVÄNDS till RGB|HSB|ScrollRows istf.MouseMove.}

 

RENSA-blocket: Inmatning av RGB eller HSB-värden kan ske manuellt med Alt+NumPad 0..9 i TRE siffror (0 skrivs då 000):

— ÅNGRAR man sig (efter typ 53 ... jä..) rensas inslaget med visningen ”Clear” på Statusradens Label1 om man släpper upp Alt-tangenten. Sedan är det bara att slå om.

— Typen Alt+”5378” resulterar bara i ”255”, övriga sätt ignoreras.

 

 

Se DELPHI4-koden för de tre övriga procedurerna ovan särskilt i

EditColorsUnit1C.

 

 

 

 

 

Ytterligare OUNDGÄNGLIGA FLYTBILDStillståndsSÄTT med enkla tangenttryckningar [Se HIMRV]:

 

H                     vändHorisontellt

V                     vänd Vertikalt

R                      Rotera i steg om +90°

M                     Tona (motVitt)[Vid programstart, börja från 50%]

NumPad+           ÖkaToning (max100)

NumPad–           MinskaToning (min0)

 

Space+H           färgvänd RGB till BGR (MånskensFärger blir SolUppgångsDito och v.v.)

NumPad0           visa färgenUnderPeken i RGB(0-255) och HSB(0-255)

Space+NumPad0 Som ovan men kopieras i text till Urklipp

 

Sedan vi infört STECKREKTANGEL med uttagsfunktioner:

 

Ctrl+D               Duplicera

Ctrl+Shift+D       FlyttaUt (samma som ovan men originalet under raderas)

Ctrl+C               Kopiera till Urklipp

Ctrl+X               Klipp ut till Urklipp

Ctrl+Delete        Radera (alt.ev. Ctrl+E[rase])

 

Ctrl+ T              Text (läggs ut som flytbild | Fet, kursiv, AllaSTORAellersmå m.m.)

T                     Som ovan efter första (senast finns kvar)

 

Unit2=Unit1A

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Med ovanstående, vidare utvidgningar i DEN ELEMENTÄRA (DELPHI4) programkoden för ett ELEMENÄRT flytbildsverktyg (P2), introduceras vi (allt mer) för SYSTEMATISKA STRUKTURER:

— kodblock med inre SPECIELLA sammansättningar och inbördes beroenden som INTE DIREKT hör till formytans komponenter.

— För att (något) skilja dessa kodDepartement åt (Programfönstrets KodBasic, Bildhanteringens olika KodBasic) väljer jag här att införa en ny komplementär Unit (’Unit2’) till Unit1, och som här kommer att namndöpas om till Unit1A (med ev. vidare Unit1B, Unit1C, osv.) — för att reservera ev. kommande ENKLA grepp åt DELPHI4 själv om man vill införa ytterligare FORMytor i projektet: DELPHI4 tillordnar då automatiskt Form2 med Unit2, Form3 med Unit3, osv. Det finns ingen anledning att bryta tillfället att utnyttjade den enkla självserveringen.

 

Alt+F, New ..., Unit, Enter resulterar i att DELPHI4 lägger ut ett nytt kodfönster som ser ut så:

 

 

Vad DELPHI4 lägger till automatiskt vid införd ny enhet.

 

Inget mer. Inget mindre.

— Kompilera direkt med Ctrl+F9, och kör sedan med F9:

DELPHI4 lägger nu DIREKT som första händelse ut en dialogbox:

 


Notera att DELPHI4 ovanstående dialog INTE kommer upp MED KATALOGEN MARKERAD SAMMA SOM DET SENAST ÖPPNADE PROJEKTET utan det senaste sparade projektet.

   Är man inte uppmärksam på det — man tror (utan att direkt läsa dialogens detaljer) att »sparkatalogen är samma som projektkatalogen» — kan ett ENTER resultera i att den nya enheten sparas på helt fel plats. I så fall: Bläddra fram till aktuell projektkatalog och spara om, och gå sedan till felkatalogen och radera felsparfilen därifrån manuellt.

 

— Ändra namnet ”Unit2” till ”Unit1A”, sedan Enter.

— Avsluta sedan P2 (Alt+F4).

 

Vi ska nu PREPARERA den nya Enheten Unit1A och göra den direkt KODKOMPATIBEL med Unit1 (samt sedan, vidare ev. övriga Units).

— För att göra det behöver vi göra olika tillägg (Här markerade särskilt med ljusgult och orange text). Dessa finns sammanställda nedan med inlagda förklaringsblock som rubricerar de olika partierna.

   För särskild förklaring, se sammanställning i UnitRubrikerna.

   Hela blocket med enheter i uses nedan är samtliga de (främsta) som behövs (min erfarenhet) för att kunna koda DELPHI4 optimalt. Testa att ta bort de som inte behövs: Om någon enhet tas bort som behövs, meddelar DELPHI det (går inte att kompilera, då).

Procedure ExecuteHRV har här lagts in som inledande exempel på hur procedurer ska deklareras i en separat Unit i DELPHI4.

 

Unit1A, UnitRUBRIKERNA

Elementär flytbildsteknik — grundexempel i DELPHI4

 

 

Den nydöpta enheten Unit1A..

 

unit Unit1A;

{Unit1A|12Sep2014|BildHanteringsRutiner|TillUnit1.}

 

interface

uses

Windows, Messages, SysUtils, WinTypes, WinProcs,

Classes, Graphics, Forms, Dialogs, StdCtrls,

FileCtrl,ExtCtrls, Controls, ShellAPI,

Math, Clipbrd, ComCtrls;

{GlobalVARIABLES|Constants .....................................:}

 

{GlobalVARIABLES|Constants ......................................}

{GlobalPROCEDURES & Functions — GlobalDeclarations .............:}

Procedure ExecuteHRV(SourceIm: TImage; Key: Word);

{GlobalPROCEDURES & Functions — GlobalDeclarations ..............}

implementation

uses

Unit1;

{MOTSVARANDE »uses Unit1A» måste tillfogas på Unit1 antingen

1. i |uses| direkt efter |interface| LÄNGST UPP — om detaljer som står

explicit under Unit1:s Interface används, eller

2. som närmast ovan i Unit1-makens Implementation|Uses.

— Se dessa detaljer utförligt i DELPHI4help,

Circular unit references: regeln är att Unit:s inte får referera

varandra i samma uses-block|Delphi vägrar kompilera då.}

{LocalVARIABLES|Constants ......................................:}

 

{LocalVARIABLES|Constants .......................................}

{ActualPROCEDURES & Functions - - - - - - - - - - - - - - - - - :}

Procedure ExecuteHRV(SourceIm: TImage; Key: Word);

begin

exit;

end;

{ActualPROCEDURES & Functions - - - - - - - - - - - - - - - - - .}

end.

 

Motsvarande uses Unit1A på Unit1 införs ENKLAST OCH KONSEKVENT ALLTID (alternativet i 1 ovan) längst upp enligt

 

 

— Importera ovanstående tillägg, och VERIFIERA med kompilering Ctrl+F9 och körning F9:

— Projektet P2 är nu färdigt att använda den nya enheten med full pedal.

 

Lägg märke till följande:

— olikheten i Unit1A mot Unit1 i GlobalaLokalaProcedurDeklarationer:

 

OM vi —som i Unit1 som HAR en egen Form1 där alla Globalt deklarerade ImplementationProcedurNamn MÅSTE börja med ”TForm1.” — testar att deklarera ImplementationProceduren ovan på formen

 

Procedure TForm1.ExecuteHRV(SourceIm: TImage; Key: Word);

 

vägrar DELPHI4 att kompilera med upplysningen

 

[Error] Unit1A.pas(30): ';' expected but '.' found

[Error] Unit1A.pas(13): Unsatisfied forward or external declaration: 'ExecuteHRV'

[Fatal Error] P2.dpr(6): Could not compile used unit 'Unit1A.pas'

— Tryck TAB (eller klicka på kodfönstret) för att komma tillbaka till kodfönstret sedan Meddelandefönstret klickats av,

 

Alltså:

— I den separata Unit-enheten (här Unit1A som ovan):

— Utelämna den inledande typen ”TForm1.” från alla procedurNamn;

— För att kunna ANVÄNDA Form1-komponenterna SOM OM UNIT1A NU VORE EN INTEGRERAD DEL AV UNIT1, börja ALLTID varje procedur i begin med exemplifierat

 

Procedure ExecuteHRV(SourceIm: TImage; Key: Word);

begin with Form1 do begin

exit;

end;{endWithForm1}

end;{endExecuteHRV}

 

Då fungerar det utmärkt.

— Skriv sedan alla variabler i Unit1A — SOM SKA KUNNA LÄSAS AV OCKSÅ Unit1 — längst upp i det anvisade blocket ovan [GlobalVariables].

— Alternativt, för enstaka förekomster, om inte ”with Form1 do begin” används, måste varje Form1-komponents användning i Unit1A inledas med ett ”Form1.”,

t.ex. Form1.Label1.Caption:= .. .

 

FÖRUTSATT att nu en viss procedur är deklarerad Globalt i Unit1A, kan den nås OMEDELBART från Unit1 med direktkommandot, här exemplifierat (t.ex. från FormKeyDown),

 

ExecuteHRV(Image2,Key);

 

Det är allt.

— På samma sätt kan Unit1A använda och utnyttja alla globalt deklarerade procedurer i Unit1 med samma typ av enkla anrop, t.ex. BitMapRect(R,B); förutsatt R och B känns igen internt i Unit1A, eller kopplar globalt för alla.

 

Alla föregående ev. deklarerade lokala globaler i Unit 1 (under Implementation) och som nu kommer att användas av Unit1A måste vi flytta upp i GlobalSektionen (efter Uses under Interface) Unit1, annars syns de inte för Unit1A. Vi förutsätter här den operationen bekant och anger den inte vidare i framställningen: DELPHI4 säger i vilket fall till om vi glömt något.

 

   OK. Då kan vi börja resan in till det verkliga äventyret.

 

StreckRektangeln, markeringar för uttag

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Streckrektangeln

 

Första åtgärden, vidareutvecklingen av Projekt P2.

— Vi fortsätter att hålla oss ett tag till i Unit1.

 

Utan ett verktyg — streckrektangel — som kan markera eller ta ut önskade partier för olika ändamål — kopiera, duplicera, radera, vända, rotera, invertera — är det ELEMENTÄRA flytbildsprogrammet fortfarande bara ett halvdant dito.

 

Hur DELPHI4-kodar man en streckrektangel — vars bildyta sedan kan användas för olika bildhanteringsändamål?

 

Image1MouseDown (Image1 Object Inspector F11, OnMouseDown, Ctrl+Enter) skriver vi in koden (globala variabler Xm0,Ym0,Xm1,Ym1: Integer;)

 

  if (Button=mbLeft)then

    begin

      Image1.Cursor:= crArrow;

      Image1.Canvas.Pen.Width:= 1;

 

      SCRIm1.TopLeft:=Image1.ClientOrigin;

      SCRIm1.BottomRight:= Point(

      Image1.ClientOrigin.X +

      Image1.ClientWidth+1,

      Image1.ClientOrigin.Y +

      Image1.ClientHeight+1 );

 

{INITIERAR STRECKREKTANGELN:}

      Image1.Canvas.Rectangle(Xm0,Ym0,Xm1,Ym1);

{Raderar föregående, XOR-styrd|Här markeras startpunkten:}

      Xm0:=X; Ym0:=Y;

      Xm1:=X; Ym1:=Y;

    end;{endIfButtonLeft}

    {Om man sätter koordinatblocket på denna plats,}

    {Xm0:=X; Ym0:=Y;

     Xm1:=X; Ym1:=Y;}

    {konserveras streckrektangeln med högerklick,

    den kan sedan inte klickas bort.}

 

Image1MouseMove verkställs motsvarande

 

  //Screen.Cursor:= MC1

  {STRECKREKTANGELN:}

  with Image1.Canvas do begin

    Brush.Color:=clWhite;

    with Pen do begin

     Color:= 0;

     Style:= psDot;

     Mode:= pmNotXor;

    end;

    if(Shift=[ssLeft])and(PtInRect(SCRIm1,CursP)=True)then

    begin

{RADERAR GAMLA:}

      Rectangle(Xm0,Ym0,Xm1,Ym1);

{RitarNya:}

      Rectangle(Xm0,Ym0,X,Y);

      Xm1:=X; Ym1:=Y;

    end;

  end;{endWithIm1Canvas}

 

Variablerna X|Y|m0|1 och CursP är speciella och kan deklareras i Unit1 som lokala (i ImplementationBlocket)

 

var

  CursP:             TPoint;

  Xm0,Xm1,Ym0,Ym1:   Integer; {MarkRectMouseMove}

 

Vi kontrollerar att streckrektangeln fungerar (Peken nedan förminskad kopia av originalet för att inte distrahera|sammanblanda med normalpeken):

 

 

Perfekt funktion.

— Men Peken kan flyttas utanför fönsterkanterna, medan streckrektangeln begränsas av bildytan (Image1).

— Hur löser vi det?

 

EMELLERTID:

— Streckrektangeln, men inte Peken, håller sig inom Image1-ytan med MusVä nedtryckt: Peken kan obehindrat flyttas ut utanför det aktuella avgränsade MÖJLIGA streckrektangelområdet.

   Vi skulle vilja att Peken stannar inom Image1-området, oberoende av vidare musrörelser.

ClipCursor:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

ClipCursor

Peken stannar inom Image1-området så länge MusVänster hålls nedtryckt,

oberoende av vidare musrörelser

 

Funktionen för det finns särskilt i Windows API och heter ClipCursor.

— VARNING:

— Följande DELPHI4-kod är utformad, testat, prövad och fungerar oklanderligt:

Vill du försöka själv att testa med ClipCursorFunktionen — den är WindowsSystemBaserad, vilket innebär att den är en DeladResurs för alla WindowsProgram:

— missar man något i kod här, kommer datorns muspekarfunktion garanterat att låsa sig, garanterat.

Enda sättet i så fall: dra ur pluggen: starta om datorn.

— OM du vill testa DELPHI4 på det sättet, FÖRBERED DIG:

— se först till att ha typ AKTIVITETSHANTERAREN öppen, för säkerhets skull, eller annat möjligt TANGENTTILLGÄNGLIGT hjälpfönster som kan nås och på den vägen ev. starta om datorn.

— Är du det minsta tveksam till den typen av Test: avstå.

 

Här är DELPHI4-koden som får ClipCursor att fungera perfekt:

 

1.

En global Pointer-rektangel deklareras på Unit1: PR: PRect;

En global Sim1-rektangel deklareras på Unit1: Sim1: TRect;

En global SCRIm1-rektangel finns här redan insatt från tidigare;

 

Försöker man deklarera alla de 3 ClipCursor-variabler som ingår — SCRIm1, Sim1, PR — i skilda sektioner lokalt och globalt ger DELPHI4 meddelandet vid försök att kompilera Ctrl+F9 (här Sim1 separat lokalt),

[Hint] Unit1.pas(98): Variable 'Sim1' is declared but never used in 'Unit1'”.

   Det är den visst det. Men ...

— »Never used» — Trots att Koden (3 nedan) på MouseUp använder just Sim1.

   Flyttas alla tre ingående variablerna till samma variabelsektion upphör mysterierna.

— Vi väljer här att sätta dem globalt, vilket ger snabbast möjliga åtkomst i alla lägen.

2.

På Image1MouseDown lägger vi till koden

 

        GetMem(PR, SizeOf(Sim1));

        PR^:= SCRIm1;

        Screen.Cursor:= crDefault;

        ClipCursor(PR);

3.

Image1MouseUp (Image1 Object Inspector F11, OnMouseUp, Ctrl+Enter) verkställs den slutliga operationen i kod som avslutar ClipCursorSessionen:

 

 if Button=mbLeft then begin

   FreeMem(PR,SizeOf(Sim1));

   PR:= nil;

   ClipCursor(PR);

   CurFlag:=0;

   UpdateInsertFlag;

 end;

 

Ovanstående insatt ska fungera oklanderligt, från första stund.

— Vi återkommer senare till CurFlag (deklarerad Curflag: Integer;) och UpdateInsertFlag.

 

 

Nu stannar Peken kvar inom Image1-ytan så länge MusVä hålls nedtryckt.

— Klick på bildytan tar bort rektangeln

 

Streckrektangeln, StädKod

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Städkod för streckrektangel

 

Vi behöver säkra ev. rester om vi ångrar initieringen eller bara vill ta bort streckrektangeln utan att göra något, utom att klicka av den med MusVäKlick förstås.

— Koden nedan införd på FormKeyDown med DELS Escape-tangenten och DELS på F2 (Rensa hela bildytan):

 

      VK_ESCAPE:begin

                  if Xm0<>Xm1 then

                  {StreckRektangel finns:}

                  begin

                   Image1.Canvas.Rectangle(Xm0,Ym0,Xm1,Ym1);

                   Xm0:=Xm1;

                   Ym0:=Ym1;

                   CurFlag:= 0;

                   UpdateInsertFlag;

                  end;

                end;{endEscape}

 

— Vi återkommer senare till CurFlag och delproceduren UpdateInsertFlag.

   Streckrektangeln dras med XNor-funktion (påverkar inte övrigt bildunderlag). Vilket betyder att om en XNor-rit finns kvar vi bara behöver upprepa den en gång till (på samma koordinater som sist) för att få bort den.

   Tillägget på VK_F2 för att säkra att streckrektangeln inte kommer tillbaka vid nästa MusVäKlick:

 

  {NOLLSTÄLL INSÄTTNINGSPUNKTER FÖLR FLYTBILD:}

                  X0:=0;

                  Y0:=0;

  {NOLLSTÄLL STRECKREKTANGEL:}

                  Xm0:=Xm1;

                  Ym0:=Ym1;

 

Streckrektangeln, Synkronisering

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Streckrektangelns SYNKRONISERING

 

 

Ytterligare en detalj krävs för att streckrektangeln ska fungera — utan att DELPHI4 pajar ihop — MED SÄKRADE MUSDRAGNINGSMÅTT:

 

Delphi pajar ihop helt och hållet om Left/Top blir mindre än

Right/Bottom — på CopyRect-funktionen. Med

Rectangle-funktionen har det aldrig funnits

några sådana problem.

 

   Med alla möjliga SÄTT att dra streckrektangeln uppkommer, strax, möjligheten att få NEGATIVA KOORDINATVÄRDEN i bestämningen av början och slutpunkter: vi vill definitivt inte ha sådana. Delphiprogrammet kraschar då.

— Streckrektangeln måste under alla omständigheter kunna redovisa EN ENTYDIGT DEFINIERAD LeftTopRightBottom-rektangel i slutänden som anvisar arbetsytan för samtliga möjliga efterföljande operationer.

 

Så här ser den väl beprövade säkringen för synkronisering av streckrektangelns fyra koordinater ut:

 

{Allmänna villkor · Endast om streckrektangel finns:}

 X:=0; Y:=0; X1:=0; Y1:=0;

 if (Xm0<>Xm1)and(Ym0<>Ym1) then

 begin

  if Xm1>Xm0 then       begin

  X:= Xm0; X1:=Xm1;     end;

  if Xm0>Xm1 then       begin

  X1:=Xm0+1; X:= Xm1;   end;

  if Ym1>Ym0 then       begin

  Y:= Ym0; Y1:=Ym1;     end;

  if Ym0>Ym1 then       begin

  Y1:=Ym0+1; Y:= Ym1;   end;

{Gäller samtliga fall|HIMRV:}

{Slutrektangeln|OPERATIVA STRECKREKTANGELN|LeftTopRightBottom:}

  Rekt:= Rect(X,Y,X1,Y1);

{Denna sista rad tar bort streckrektangeln:}

  Image1.Canvas.Rectangle(Xm0,Ym0,Xm1,Ym1);

{AnnarsÅterEfterAvslutMedMusVäNer:}

  Xm0:=Xm1; Ym0:=Ym1;

...

 end;

 

Streckrektangeln, CursorFlag

Elementär flytbildsteknik — grundexempel i DELPHI4

 

CurFlag och UpdateInsertFlag

 

Har du märkt (ibland — speciellt omkring ”eran” Windows XP) det här:

— Man prickar in (manuellt) stället man vill börja dra eller göra en marking med en streckrektangel för att ta ut något parti.

— I samma ögonblick man trycker ner vänster musknapp inträffar följande Roliga Tilltag:

 

den surt förvärvade Pekpositionen HOPPAR (flera pixels) till någon ny Intern Position — på grund av att den snabba datorn med den känsliga musplattan hinner uppfatta smärre mikrorörelser med handen innan Klicket kopplar.

   Ajö med den precisionen.

 

Här är Boten:

— Placera Peken, Tryck INSERT där insättningspunkten önskas: insättningspunkten SPARAS.

 

1: 2: 3: 4:

 

1: Insert No1 vid Peken:

— Bottenpanelen (Panel2) skjuts 24 pixels åt höger för att ge plats för en grön InsertFlagga: Koordinaterna vid Insert No1 sparas och står kvar i den svarta X;Y.displayen: Peken kan röras fritt.

2: När sedan Musknapp vänster trycks ner, hoppar Peken till den sparade insättningspunkten, och Streckrektangeln kan nu börja dras:

— Manuellt eller/och med piltangenterna kan även en slutposition bestämmas exakt med en Insert No2:

3: Insert No2 frikopplar Peken från streckrektangeln och lägger in en motsvarande KlarFlagga. Med fortsatt MusVä nedtryckt kan Peken flyttas oberoende av streckrektangeln. Kopplingen har upphört.

4: Streckrektangeln raderas först med ett nästa MusVäKlick, ett Esc eller i samband med (kommande) operationer på den markerade bildytan. Bottenpanelen (Panel2) skjuts tillbaka i normalläge

— Naturligtvis finns också det vanliga klassiska normala KlickaMusVänsterDirekt-alternativet kvar.

 

— Musen kan sedan röras fritt (tryck ESCape om Ångra):

— Så snart MusVä trycks ner HOPPAR Peken DIT Insert sattes och streckrektangeln kan nu dras med perfekt exakt precision.

— En andra INSERT No2 (om så önskas) frikopplar Peken HELT från streckrektangeln VID Insertpositionen.

— Därmed är exakta positioner vid Insert1o2 garanterade.

 

Ofta förekommande (min erfarenhet):

— HOME Insert, nyligen intaget (något objekt via Ctrl+V). Peken till LeftTop med insättningspunkten 0;0 preparerad. Superfint.

 

 

Projektet P2, så långt [12Sep2014]

Den nuvarande 11Sep2014 (från 4Sep) samlingen filer i projektkatalogen för P2.

 

 

 

Streckrektangeln, FlaggIkonerna

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Flaggikonerna

Flaggikonerna finns sparade som bmp-filer i projektkatalogen som respektive

FLAGUP.BMP och FLAG.BMP.

— Koden i DELPHI4 som verkställer helheten ovan lyder:

 

Image1MouseDown:

    if (Button=mbLeft)then

      begin

        Image1.Canvas.Pen.Width:= 1;

        Image1.Cursor:= crArrow;

        Screen.Cursor:= crArrow;

{omINSÄTTNINGSFLAGGA VIA KEY INSERT:}

        if CurFlag=1 then

        begin

          SetCursorPos(CurP.X,CurP.Y);

          CurP:= Image1.ScreenToClient(CurP);

          X:= CurP.X; Y:=CurP.Y;

          CurFlag:=0;

          UpdateInsertFlag;

        end;

{UPPDATERA KOORDINATER:}

        SCRIm1.TopLeft:=Image1.ClientOrigin;

        SCRIm1.BottomRight:= Point(

        Image1.ClientOrigin.X +

        Image1.ClientWidth+1,

        Image1.ClientOrigin.Y +

        Image1.ClientHeight+1 );

{CLIPcURSOR:}

        GetMem(PR, SizeOf(Sim1));

        PR^:= SCRIm1;

        Screen.Cursor:= crDefault;

        ClipCursor(PR);

{INITIERAR STRECKREKTANGELN:}

        Image1.Canvas.Rectangle(Xm0,Ym0,Xm1,Ym1);

{Raderar föregående, XOR-styrd|Här markeras startpunkten:}

        Xm0:=X; Ym0:=Y;

        Xm1:=X; Ym1:=Y;

    ...

Image1MouseMove:

{FrikopplarPeken från Streckrektangeln om InsertNo2:}

             if CurFlag=1 then exit;

             ...

{LeftMouseBUTTON:}

                  if Shift=[ssLeft] then

                  begin

                    Screen.Cursor:= crArrow;

{STRECKREKTANGELN:}

                    with Image1.Canvas do begin

                      Brush.Color:=clWhite;

                      with Pen do begin

                       Color:= 0;

                       Style:= psDot;

                       Mode:= pmNotXor;

                      end;

                      if(Shift=[ssLeft])and(PtInRect(SCRIm1,CursP)=True)then

                      begin

{RADERAR GAMLA:}        Rectangle(Xm0,Ym0,Xm1,Ym1);

{RitarNya:}             Rectangle(Xm0,Ym0,X,Y);

                        Xm1:=X; Ym1:=Y;

                      end;

                    end;{endWithIm1Canvas}

                  end else Screen.Cursor:= MC1;

Image1MouseUp:

                  if Button=mbLeft then begin

                    FreeMem(PR,SizeOf(Sim1));

                    PR:= nil;

                    ClipCursor(PR);

                    CurFlag:=0;

                    UpdateInsertFlag;

                  end;

 

UpdateInsertFlag — separat globalt deklarerad procedur på nyinrättade Unit1A:

 

Procedure UpdateInsertFlag;

var

 B: TBitMap;

 S: string;

 R: TRect;

begin with Form1 do begin

          R:= Bounds(0,Height-25-23,23,21);

{CurFlag=0:}

          if CurFlag=0 then

          {DeleteKey:}

          begin

                Canvas.Brush.Color:= clBtnFace;

                Canvas.FillRect(R);

                Panel2.Left:= 0;

                 GetCursorPos(CurP);

                 {Action to update Panel4Coordinates:}

                 SetCursorPos(CurP.X+1,CurP.Y);

                 SetCursorPos(CurP.X,CurP.Y);

          end{endCurFlag=0}

          else

{CurFlag=1:}

          begin

{MouseLeftIsDown:}

                 if GetKeyState(VK_LBUTTON)<=-127 then

                 S:='FLAGUP.BMP' else S:='FLAG.BMP';

                 if not FileExists(S) then

                 begin

                    Label1.Caption:='Flag*.bmp·NotFound';

                    exit;

                 end;

                 B:= TBitmap.Create;

                 try

                    B.LoadFromFile(S);

                    //B.Transparent:= True;

                    //B.TransparentColor:= clWhite;

                    Panel2.Left:= 24;

                    Canvas.Brush.Color:= clWhite;

                    Canvas.FillRect(R);

                    Canvas.Draw(5,Height-23-23,B);

                 finally

                    B.Free;

                 end;

          end;{endCurFlag=1}

end;{endWithForm1}

end; {endUpdateInsertFlag}

 

Används Transparensen för BitMap B (avställt ovan med //) ritas flaggikonerna direkt som fristående figurer utan deras bildrektangels täckning på den ljusgrå Form1-ytan.

 

 

PROGRAMDIVERGENS, kPD

Elementär flytbildsteknik — grundexempel i DELPHI4

 

Allmän kommentar

kodrelaterad

PROGRAMDIVERGENS

 

KODBLOCKEN OVAN I SAMARBETE — MouseDown|Move|Up — är ett utmärkt exempel på den PROGRAMDIVERGENS vi aldrig kommer ifrån i all (avancerad) programmering:

— Vi kan OMÖJLIGEN ha »allt samlat på samma ställe»:

 

Alla procedurer vi framställer innehåller FICKOR som man kan »stoppa in» vissa nya funktioner i:

— Det blir en FRESTELSE TILL UTMANING — som i värsta fall resulterar i en veritabel »myrstack» av instoppade kodavsnitt som bara i efterhand kan begripas ENDAST med STOR svårighet — speciellt av den som satt ihop påtet.

— Med NOGGRANNA KOMMENTARER OCH FÖRKLARINGAR KAN en sådan »myrstack» förvandlas till rena gudomliga Romanen, förutsatt TID att beskriva allt i detalj.

 

Foto:  27Aug2014  Bild11  E18

 

 

En liten sjö håller på att växa igen — supervarma somrar. Bara för några få år sedan, helt öppen. Nu alltmer fylld av bottenuppväxande gräs och näckrosväxter.

 

Det finns ALLTID en stam, ett rotverk, och över det ett grenverk med BLAD längst ut: allt åtskilt av OBÖNHÖRLIG distans.

— »Distansen mellan kodblocken» ÄR utmaningen i datorprogrammering:

— RÄTT ansats ger programmeringen som helhet en tendens att vara KONVERGENT: satsbilder, kopplingar, anslutningar, fungerar som ett TRÄD: samlat, snyggt, oerhört ändamålsenligt.

— ASSOCIATIVT leder den typen till FOKUS.

— »FEL ansats» ger DIVERGENTA flöden: ju mera man lägger till, desto mer OBEGRIPLIG, svårhanterlig, OFOKUSERAD och obändigt KOMPLICERAD blir helheten: »Trädet» blir snarare en »odefinierad Explosion» — i utveckling. Domaren är du, och jag. (»Nej, det här går inte ..»).

 

 

KODORGANISATION SOM MOTVERKAR DIVERGENT PROGRAMMERING — exempel

 

Speciellt bilder (Image) och paneler (Panel) är i alla datorprogram föremål för olika åtkomstmanövrer:

 

1. KlickaPå

2. MusRörelserÖver

3. MustangenterHögerVänster|NerUpp

4. Mushjul

 

Vi kan i DELPHI4 FÖR VARJE ENSKILD KOMPONENT (som har dessa egenskaper) skapa särskilda direkt DELPHI4-genererade procedurer genom Object Inspector (F11, den komponenten), markera aktuell händelseform, och trycka Ctrl+Enter. DELPHI4 lägger då automatiskt in startfrasen för den proceduren, och vi behöver bara fylla i ev. variabler över begin och sedan skriva verkställande programkod mellan begin och end.

 

Hur DELPHI4 initierar en komponentprocedur

procedure TForm1.FormClick(Sender: TObject);

begin

 

end;

 

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

begin

 

end;

 

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,

  Y: Integer);

begin

 

end;

 

...

 

Om komponenternas antal tenderar att bli av typen större, får (min erfarenhet och mening) dessa separata procedurblock en tendens att just uppvisa DIVERGENS i programmeringen.

— Nämligen med följande jämförande alternativ:

— Vi använder för SAMTLIGA MouseKlick-MouseDown-MouseMove-MouseUp ETT OCH SAMMA procedurblock. Nämligen det som gäller för programfönstrets Form(MouseKlick-MouseDown-MouseMove-MouseUp).

 

SJÄLVA ANLEDNINGEN bakom DET alternativet (enligt min erfarenhet):

— EN VISS KOMPONENT — som också ibland kan LÅNAS/delas mellan olika programavsnitt — tenderar (allt eftersom programmet växer i kod) att hamna i ett programflöde som INTE DIREKT kopplar till Form1|Unit1 — typ separat RitProgram, separat Grafprogram, separat BildHantering (Unit1A), separata Specialrutiner särskilt (Unit1B), separat FärgAnalys(Unit1C) ... : separat insatta Unit:s för att skilja programavsnitten åt, att göra kodläsning, redigering och utveckling maximalt överskådlig — alltid med noggrant utformade kommentarer och förklaringar.

— Nämligen just UTSTRÄCKNINGEN av dessa antydda individuella specialprocedurer (och sedan i sin tur deras förgreningar, om alls):

Unit1-procedurerna TENDERAR nämligen att bli långdragna KodAvhandlingar i takt med att programmet (och dess oerhörda DELPHI4-potential upptäcks, och därmed) utvecklas, om man helt villkorslöst OCH ÖVERALLT följer den enkla DELPH4-ordningen exemplifierad ovan:

— Man får leta — hoppa omkring inom långa kodavsnitt VILKET SAMTIDIGT TAR FOKUS FRÅN mera viktiga AKTUELLA VIKTIGA PROGRAMKONCEPT under utformning.

— Nämligen det som alla som programmerat något redan möjligen upptäckt: mängden UPPSLAG i programmering i löpande associativ takt under arbetets fortlöpande är ENORM: för att MATCHA den associativa tankeströmmen UTAN ATT STÖRAS är det avgörande viktigt att MELLANLIGGANDE EFTERSÖK INTE FÅR TA FÖR LÅNG TID, för då TAPPAR MAN TRÅDEN, speciellt om uppslaget man har i sin tanke är av typen MERA KOMPLICERAT. Det har ingenting med ÅLDERN att göra (min erfarenhet). Det handlar om FÖRMÅGAN ATT HÅLLA X BOLLAR I ORDNAD RÖRELSE I LUFTEN SAMTIDIGT.

— Ett samlad programkoncept gör sådana utflykter med uppslag till en ren NJUTNING. Ligger däremot koden man letar efter utspridd på många olika ställen, hinner man tappa suget innan något kopplar: man glömmer plötsligt av vad det var man skulle leta efter. Jag har observerat det fenomenet ända från mina barnsben upp till nu (2014). Och det är ALLTID på samma sätt: har för många bollar i luften samtidigt.

   Det man missade, som man tänkte på, KOMMER ALLTID UNDANTAGSLÖST TILLBAKA — OM man praktiserar följande enkla recept: Ta en paus. Stäng av datorn. Koppla av. Förr eller senare »knackar det på dörrn». Håll bara ut med avkopplingen, hetsa inte. Säkert som amen i kyrkan.

 

Hur gör man då i DELPHI4 för att säkra en »MERA fokuserad» programordning?

 

För att effektivt motverka en klart divergent programbild — olika programavsnitt man HELST vill se i ett SAMLADT kodblock, inte med utspridda kopplingar på olika ställen — behöver vi ett DISTRIBUTIONSNAV — ett distributionscenter — i varje typ Form(MouseKlick-MouseDown-MouseMove-MouseUp). Vi behöver också ett sådant särskilt på det avgörande FormKeyDown för att kunna säkra avgränsade programdomäner och deras privata KeyDown-rutiner.

— ALTERNATIVET är att KeyDown-rutinerna — som var tänkta att leda till de olika avsnitten genom KORTA kommandon — tenderar att bli veritabla villkorsAvhandlingar — långa, dryga kodavsnitt med specialvariabler för att gardera och säkra — med allt växande svårighet i GEMENSAM ÖVERSIKT.

 

HELP, F1 — exempel

Exempel som introducerar typen »distributionsnav» — F1

 

 

I Projektet P2 — elementär flytbildshantering — vill vi SOM TILLÄMPNINGSEXEMPEL [se speciellt Punkt5 nedan] mötas av det här när programmet startar upp:

 

 

— Ett INTRODUKTIONSinfo som inte stör den normala tangentåtkomsten:

 

·         Vänsterklick på introbilden öppar upp ett htm-dokument med programHjälp;
— En P2Help.htm-fil finns preparerad i en separat underkatalog Help som skapats särskilt för ändamålet,
,
     

— Separat tangent
F1 leder också dit, FormKeyDown.

·         Valfri tangent (utom PrtScn) tar bort introbilden;

·         När introbilden försvinner framträder en liten I-panel nederst höger,

den fungerar som KlickIkon (med en Hint, ”Key § ¦ InfoP2”) för att få IntroBilden åter. Klickar man på den (eller använder tangent §) kommer infobilden åter och i-panelen försvinner. Osv.

 

Infobilden som sådan kan utvecklas (mycket) avancerat med indelning i olika bildrektanglar (åtkomst via MouseMove): interna understrukturer: Högerklick kan t.ex. användas för att bläddra bland inforemsorna = programbeskrivningar på komprimerad kortform — och vänsterklick för motsvarande direkt åtkomst till separat htm-dokument som beskriver innehållet mera i detalj.

   Vi ska (i varje fall ännu) inte avhandla den möjligheten här, bara omnämner möjligheten.

ÖppnaHELPhtm

Välkomstbild med HELPinfo

Panel11|Image4

Komponenter och kod i DELPHI4 som realiserar ovanstående — öppna HELP-htm:

 

1. En ny Panel11 med en ny bild Image4 bildar en enhetlig komponentgrund (Enklast: kopiera Panel1 med Image1: håll MusVä nere och dra streckrektangel över bägge Pan1Im1, släpp upp, Ctrl+C, klicka sedan på Form1 och ta in med Ctrl+V: ändra egenskaper separat):

 

 

Med Image4 täckande över Panel11 för att komma åt Panel11Markering: Klicka på Image4, tryck ESCape.

 

Egenskaperna (övriga orörda) för Panel11 på Object Inspector:

Visible True(alltid); Width 50; Height 50; HändelseKopplingarna:

OnClick FormClick; OnMouseMove FormMouseMove;

 

Egenskaperna för Image4 (nu Parent= Panel11) på Object Inspector:

AutoSize True; Visible False; Width 50; Height 50 (efter AlClient, AlNone);

Visible True(alltid); Width 50; Height 50;

Dessa justeras sedan senare separat i vilket fall via kod; HändelseKopplingarna:

OnMouseDown FormMouseDown; OnMouseMove FormMouseMove;

 

2. Vi lägger till en global IntroP2: Bool; på Unit 1 — vi behöver den här egentligen inte, då användningen av Image4 som Show eller Hide kommer att fylla samma funktion; IntroP2 ger bara en starkare rent beskrivande indikering;

 

3. Vi introducerar en ny enhet Unit1B — se Unit1A hur det går till i detalj — med rubriken

 

unit Unit1B;

{Unit1B — SpecialProcessing|13Sep2014}

 

med en första global procedur Pan11:

 

{INTRO — Pan11|Image4|Key§: — anropas först från FormCreate:}

Procedure Pan11;

var

 S: string;

begin with Form1 do begin

{INTRODUKTIONSBILD med htm-hänvisning|11Sep2014:}

                S:= 'IntroP2.bmp';

                if not FileExists(S)then exit;

{SHOWinitialization|Im4HiddenFromStart|Pan11AlwaysVisible:}

                if not Image4.Visible then

                begin

                  Panel11.Parent:= Form1;

                  Panel11.Anchors:= [];

                  Panel11.Caption:= '';

                  Panel11.ShowHint:= False;

                  Panel11.BringToFront;

 

                  Image4.Picture.LoadFromFile(S);

                  Panel11.BoundsRect:= Bounds(0,0,Image4.Width+1,Image4.Height+1);

{Centrerat:}

                  Panel11.Top:= Panel1.Top  + (Image1.Height - Panel11.Height)div 2;

                  Panel11.Left:=Panel1.Left + (Image1.Width  - Panel11.Width )div 2;

                  Image4.Show;

                  IntroP2:= True;

                  exit;

                end;{endIfInfoP2Visible}

{ShowAs|i-Button|TopRight|AnyKeyDownFromUnit1—UnlessExceptionS:}

{AfterAnyKeyDown|Unit1:}

                if Image4.Visible then

                begin

                  Image4.Hide;

                  IntroP2:= False;

                  with Panel11 do begin

                    Parent:= Panel2;

                    BoundsRect:= Bounds(Panel2.Width-16-2-2,1,18,17);

                    Anchors:= [akRight,akBottom];

                    ShowHint:= True;

                    Hint:= 'Key § ¦ InfoP2';

                    Font.Size:= 12;

                    Font.Style:= [fsBold];

                    Font.Color:= clWhite;

                    Font.Name:= 'Times New Roman';

                    Color:= RGB(0,149,255);

                    Caption:= 'i';

                  end;

                end;{endIfInfoP2iButton}

end;{endwITHfORM1}

end;{ENDpAN11}

 

VINSTEN FRÄMST ÄR ATT VI SLIPPER HA DEN OVAN (och alla liknande) SPECIELLA SEPARATA PROCEDURMANGLINGEN »skräpande» i UNIT 1. Rent, prydligt, snyggt.

 

4. På FormCreate skriver vi sedan in (sist) det enkla, förlösande:

 

{INTRODUKTIONSBILD med htm-hänvisning|11Sep2014: — IntroP2|Unit1B:}

               Pan11;

 

Därmed tar startexekveringen automatisk vägen över till Unit1B, Pan11Proceduren ovan, och laddar in IntroBilden.

— Introbilden som sådan (IntroP2.bmp) finns inlagd separat i projektkatalogen; Panel11.måtten anpassas som ovan automatiskt till den bildens mått.

 

5. På FormKeyDown skrivs nu SOM TILLÄMPNINGSEXEMPEL motsvarande DISTRIBUTION:

 

  {INTRODUKTIONSinfo|Unit1B:}

                if IntroP2 then Pan11 else

                if Key=Ord(220) then Pan11;

  {Ord220=Key|§|Paragraph|StartUpProgramItems|Unit1B.}

 

Slutligen skriver vi först in HÄNDELSEKOPPLINGARNA via procedurerna på Form1 och sedan proceduren för htm-dokumentens öppning:

— Vi inrättar först speciella allmänna DISTRIBUTIONSNAV i händelseprocedurerna OnClick|OnMouseDown|OnMouseMove, här inledningsvis för Pan11|Im4, och senare på enklare sätt för alla ytterligare:

 

{GENERAL|MouseClick|14Sep2014:}

procedure TForm1.FormClick(Sender: TObject);

begin

{FÖRDELNINGSNAV FÖR FLERA MouseClick-KOMPONENTER:}

       if Sender as TObject <> Form1 then

       begin

{Pan11|Unit1B:}

        if Sender = Panel11 then begin

          Pan11;

          exit;

        end;{endPan11|Unit1B:}

       end;

{FÖRDELNINGSNAV FÖR FLERA MouseClick-KOMPONENTER.}

  //exit;

  Label1.Caption:= ExtractFilePath(Application.ExeName);

  ClipBoard.AsText:= Label1.Caption;

end;{endFormClick}

 

{GENERAL|MouseDown|14Sep2014:}

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

begin

{FÖRDELNINGSNAV FÖR FLERA MouseDown-KOMPONENTER:}

       if Sender as TObject <> Form1 then

       begin

        if Sender = Image4 then

        begin

        if IntroP2 and(Button = mbLeft)then

        OpenHtmHelp('P2Help.htm','');

        exit;

        end;{endIfIm4|LBdown|OpenHtmHelp|Unit1B}

       end;

{FÖRDELNINGSNAV FÖR FLERA MouseDown-KOMPONENTER.}

end;{endForm1MouseDown}

 

{GENERAL|MouseMove|14Sep2014:}

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,

  Y: Integer);

begin

  Screen.Cursor:= crArrow;

end;{endForm1MouseMove}

 

Vinsten med ovanstående allmänna organisation är att man får EN ENDA ENHETLIG procedur för En Viss Händelse för alla möjliga komponenter — att jämföra med alternativet en särskild händelseprocedur för varje komponent, och som resulterar i motsvarande mängd utspridda procedurer — ofta på inbördes vitt skilda ställen i Unit:en, och därmed svåröverskådligt.

 

— Missar vi {FÖRKLARINGSPARENTESERNA} blir det för övrigt (med växande program till slut) hart när omöjligt att hitta Rätt och Snabbt. Dessa är tveklöst avgörande för överskådligheten och sammanhanget.

 

Öppningskoden för htm-dokument

 

Koden för htm-dokumentens öppning, globalt deklarerad på Unit1B (under usesBlocket), över ovanstående (under ImplementationBlocket):

 

{Unit1B:}

Procedure OpenHtmHelp(S,L: string);

var

     A,I: Integer;

     T,U: string;

begin

//S:= 'P2Help.htm';

        L:= S + L;

        U:= ExtractFilePath(Application.ExeName);

        if not FileExists(U+'Help\'+S) then begin

         Form1.Label1.Caption:= 'File ' + S + ' NotFound';

         exit;

        end;

{Skicka med ev. Htm-Länk|L till Urklipp:}

        for I:= 1 to Length(U) do

        if U[I]='\' then U[I]:= '/';

        U:= 'file:///' + U + 'Help/HTM/' + L;

        ClipBoard.AsText:= U;

{ÖPPNA:}

        T:= ExtractFilePath(Application.ExeName) + 'Help\';

        A:= ShellExecute(

        0,

        nil,

        PChar(S),

        nil,

        PChar(T),

        SW_SHOW);

{Programmet öppnar inte:}

        if A<=32 then

        Form1.Label1.Caption:= 'OpenDocumentError';

end;{endOpenHTMhelp}

 

DELPHI4 kan inte direkt åstadkomma länkhopp i ett öppnat htm-dokument.

— Däremot kommer länkstället fram med ovanstående medsända länkdel till Urklipp så:

— Tryck F6 (eller Tab i InternetExplorer), det fokuserar URL-boxen; Tryck Ctrl+V och sedan Enter.

F1 Help

Tangent F1 koppar direkt (FormKeyDown, CaseKeyBlocket):

 

 {HELP|Unit1B:}

      VK_F1:    OpenHtmHelp('P2Help.htm','');

 

Ovanstående garanterar (enligt min erfarenhet):

— En avancerad program(för)fattningsgrund med minimala möjligheter att bilda DIVERGENT programkod.

 

Distributionsnavets mera praktiskt sammansatta exempelform

 

Ovanstående programexempel med HELP innefattar egentligen alldeles för lite kod för att vara en bra praktisk exempelform på ett DISTRIBUTIONSNAV. Vartefter P2-projektet utvecklas, infinner sig emellertid allt fler möjligheter att visa och exemplifiera en mera fördjupad sammansatthet — och samtidigt exemplifiera de redan antydda fördelarna.

 

Praktiskt exempel

 

Programutvecklingen för P2 omfattar nu (4Okt2014) tre separata procedurblock som vart och ett kräver fullständig tillgång till KeyDown-nycklar, utan att inkräkta på varandras domäner. Organisationen på FormKeyDown Unit för alla dessa ser ut så, här med efterföljande kort beskrivning:

 

                SExit:= False;

                //if Key in [VK_NUMPAD5,Ord('T'),Ord('Z')]

{Den enkla formen ovan — kolliderar med Ctrl+NumPad5 för ArrowStep. För att

parera för denna måste följande mera preciserade anordning anställas:}

                if((Shift=[])                and(Key in [VK_NUMPAD5,Ord('Z')]))

                or((Shift=[])      and(WTini)and(Key in [Ord('T')]))

                or((Shift=[ssCtrl])          and(Key in [Ord('F'),Ord('T')]))

                then

                begin

                  case Key of

  {INITIALIZING||SPECIAL PROCEDURES|Takes All KeyDown .·°·.·°·.·°·.·°·.·:}

  {ACTIVATE|deActivate ·················································:}

      VK_NUMPAD5:   begin if not Busy then

                     EditColors(Key, Shift);

                    end;{endNP5|Unit1C}

        Ord('T'):   begin if not Busy then

                     if (Shift=[ssCtrl])

                     or ((Shift=[])and(WTini))

                     then

                     WriteText(Key, Shift);

                    end;{endCtrlT|Unit1T}

        Ord('Z'):   begin if not Busy then

                     ZoomGeneral(Key, Shift);

                    end;{endCtrlS|Unit1A}

  {ACTIVATE|deActivate ·················································.}

                  end;{endCaseKey}

                  if SExit then exit;

                end;{endIfSpecialProcedureModuleKeys}

  {INITIALIZING||SPECIAL PROCEDURES .·°·.·°·.·°·.·°·.·°·.·°·.·°·.·°·.·°·.}

  {IfActive|SPECIAL PROCEDURES|ModulensAktiveringsNyckel ···············:}

                if ecPanON then begin

                     EditColors(Key, Shift);

                     if SExit then exit;

                end;{EditColors|Unit1C}

                if TextWrite then begin

                     WriteText(Key, Shift);

                     if SExit then exit;

                end;{WriteText|Unit1T}

                if Im2StretchDraw then begin

                     ZoomGeneral(Key, Shift);

                     if SExit then exit;

                end;{StretchDrawIm2|Unit1A}

  {IfActive|SPECIAL PROCEDURES ·········································.}

 

Förklaring:

— Ovanstående kodblock STÅR ALLRA FÖRST i

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);

— Varje särskild KeyDownÄgare (EditColors, WriteText, ZoomGeneral) — KÄ-domän — säkrar sitt KeyDownÄgande genom att

0. specificera en unik tangentkombination KeyDown (NP5, Ctrl+T eller sedan aktiverad T, Z),

1. aktivera sin (DN) domän(ägar)nyckel (ecPanON, TextWrite, Im2StretchDraw) och

2. ange SExit:=True i den procedurens initiering (början eller slut, vilket som passar).

— KÄ-domänen avslutar sedan sitt KeyDownÄgande genom att avställa DN (=False).

— KÄ-domänen behöver aldrig verkställa SExit:=False eftersom den delen i vilket fall alltid står först i FormKeyDown.

Busy-tillståndet (Bool|True¦False) motsvarar »ett ömsesidigt handelsavtal» mellan KÄ-domänerna och som garanterar att ALLA TANGENTER — även den som aktiverar en annan domän — får användas av den aktuellt aktiva KÄ-domänen.

— Eftersom (således) bara EN aktiv KÄ-domän kan finnas vid varje tillfälle, finns ingen risk för »överhörning» mellan de skilda KÄ-domänerna: varje KÄ-domän garanteras absolut isolation mot övriga.

— Busy:=True aktiveras inifrån varje KÄ-domän i procedurens början, och måste avställas vid utgången (Busy:=False tillsammans med DN:=False).

SExit:=True innebär att ALLA EFTERFÖLJANDE ORDINÄRA KEYDOWNKOMMANDON hoppas ÖVER. Dessa berör här (i P2) f.ö. allt som innefattar Flytbildsrutiner (Ctrl+Pilar, Invertera, Rotera, Duplicera, Kopiera, Tona, m.fl. OM sådana behövs inifrån resp. KÄ, kan sådana utformas separat för just den individens behov — precis som det är i NaturFloran).

 

Med ovanstående PRINCIPIELLA uppställning, blir det nu enkelt att, i princip, lägga till »hur många som helst» ytterligare KÄ-domäner (Frame, Draw, Clone, PhotoEdit ...) UTAN ÖVERDRIVET UPPTAGANDE PLATS i själva distributionsnavet på FormKeyDown: aktiveringsnyckel (DN) och identifieringsnyckel (UnikKey) [samt GOD anteckningsTeknik] är allt som krävs.

— Enda som krävs för översikten: SKRIV IN VAR specialProcedurerna finns, så att man lätt hittar VAR vilken finns. Jag brukar LISTA alla Units i Unit1 överst med en liten förteckning som orienterar vad som finns, typ (nuvarande)

 

unit Unit1;

{Unit1   | 8Sep2014|ProjectP2 — Im123FromStart}

{Unit1A  |12Sep2014|BildHanteringsRutiner|ZoomGeneral|Merge|ExecuteHRV...}

{Unit1B  |13Sep2014|SpecialProcessing|OpenHtmHelp|Pan11Im4INTRO}

{Unit1C  |17Sep2014|EditColorsUnit}

{Unit1T  |27Sep2014|TEXTRutiner}

interface

...

 

*

 

Med ovanstående genomgångar är vi nu klara att sätta in HCDIMRVXZ-funktionerna i flytbildsprojektet P2: vänd H|orisontellt V|ertikalt D|uplicera I|nvertera M|erga R|otera X|portera C|opiera Z|oomera.

 

 

 

Projektet P2, så långt [12Sep2014] — UnitRubrikerna

Den nuvarande 11Sep2014 (från 4Sep) samlingen filer i projektkatalogen för P2.

 

 

HIMRV

CRsEmpty:=True; infört:

CRsEmpty: Bool;  Unit1 Global, sätts TRUE på ClearImage1|F2 och FALSE på första Ctrl+V — Används på Ctrl+C för att eliminera (frekvent) felinslag|Ctrl+C efter bildrensning|F2 då man vill ta in|Ctrl+V från Urklipp. Utan CRsEmpty resulterar Ctrl+C med tom bildyta att Im2VITT kopieras till Urklipp = raderad intagskopia. Elakt InslagsFel. Lösningen som ovan.

— Tillagt 18Sep2014|Unit1 FormKeyDown¦Ord('V')¦F2|Unit1A PrepareExecuteHRV¦Ord('C').

 

TABELLEN NEDAN är i sammanställning alla flytbildskommandon i P2 (20Sep2014) — Zoomning ingår inte ännu.

— Utöver dessa behövs i varje fall en ytterligare: en StretchDraw (i allmänhet mindre god bildkvalitet vid förminskningar [utom för rena fotografier], som ändå ibland kan ha viss praktisk användbarhet för GROV översikt) för bekväm GROV bildrektangelÄndringar — MED tydlig display i %-förhållanden mellan bredd/höjd relativt originalet — och via PilTangenter för EXAKT representation.

— Ett verktyg av den kalibern associerar EMELLERTID GÄRNA till Zooming UppNer: Det är här (ännu) inte bestämt eller ens känt HUR en sådan förnämlig funktion ska realiseras i ETT verktyg med ENKLA manöverspakar (»ALLT i ett»).

 

TabellHIMRV

HIMRV

 

Tangentkommandon P2¦19Sep2014|Alla FLYTBILDSOPERATIONER:

Ctrl+X|C|D|DeleteH|I|M|R|VCtrl+Shift+D

SPACE+H

 

Alla de 11+ ELEMENTÄRA flytbildsoperationerna — de BÖR vara så ENKLA att man LÄTT minns dem utantill

 

SHIFT

Key

Makes

Makes ¦ Toggle

PrepHRV

Ctrl+

I

ExportImage

 

KeyDown

Ctrl+

V

ImportFromClip

 

ja

Ctrl+

C

CopyToClip

 

ja

Ctrl+

D

Duplicate

 

ja

Ctrl+Shift

D

MOVE ¦ MarkRect

Duplicate + EraseOriginal

ja

Ctrl+

X

CutToClip

 

ja

Ctrl+

Delete

Delete = PaintWhite

 

ja

SHIFT

Key

Makes

Makes ¦ Toggle

 

SPACE+

H

RGB to BGR

 

ja

 

H

FlipHorizontal

 

ja

 

V

FlipVertical

 

ja

 

R

Rotate90°

 

ja

 

I

InvertImage

 

KeyDown

SHIFT

Key

Makes

Makes ¦ Toggle

 

 

M

Merge

OnOff

KeyDown

NumPad

+

IncreaseMergeImpact

max100%

KeyDown

NumPad

DecreaseMergeImpact

min0%

KeyDown

 

C

MoveCOPY

MoveAND

KeyDown

 

W

MoveSkipWHITE

MoveWHITE

KeyDown

SHIFT

Key

Makes

Makes ¦ Toggle

 

Ctrl+

M

MoveAsObject

MoveAs SHOW more

KeyDown

NumPad

5

EditColors

Back| Foreground

KeyDown

 

Insert

ExactMarkRectPos

 

KeyDown

 

PepHRV = PrepareExecuteHRV — ja anger om kodnyckeln leder dit

 

Allmän KODblocksOrganisation för ovanstående | projekt P2 DELPHI4|Sep2014

Koden i DELPJI4 | projekt P2 | 19Sep2014:

— Unit1¦FormKeyDown — (nästan) alla ovan sammanställda till gemensamt DISTRIBUTIONSNAV:

 

Generellt, först på FormKeyDown¦Unit1:

 

  {GENERAL¦KEYandSHIFT MIX|HIMRV:}

  if((Shift=[])      and(Key in [Ord('H'),Ord('R'),Ord('V')]))

  or((Shift=[ssCtrl])and(Key in [Ord('C'),Ord('D'),Ord('X'),VK_DELETE]))

  or((Shift=[ssShift,ssCtrl])and(Key in [Ord('D')]))

  then

  begin

   PrepareExecuteHRV(Key);

   if(Key=Ord('R'))and(MergeFlag=1)then MakeNewFleetStateVisible;

   exit;

  end;{endTo|PrepareExecuteHRV(Key)}

 

Motsvarande UTSKRIFT av SHIFT + Key på PrepareExecuteHRV(Key) ser ut så här:

 

X:=0;

if GetKeyState(VK_SHIFT)<=-127   then Inc(X);

if GetKeyState(VK_CONTROL)<=-127 then Inc(X);

if X=0 then

Label1.Caption:=                Char(Key) else

if X=1 then

Label1.Caption:= 'Ctrl+ '     + Char(Key) else

if X=2 then

Label1.Caption:= 'Ctrl+Shift '+ Char(Key) else

Label1.Caption:= 'PrepareExecuteHRV|NoKey';

 

samt särskilt på den speciella FlipRGBtoBGR (»Månskenslandskap» blir »SoluppgångsDito»)

 

Label1.Caption:= 'SPACE+ H';

 

Utskriften visas nederst på StatusRaden för varje aktivering.

 

Alla ovanstående skickas till Unit1A PrepareExecuteHRV(Key).

— PrepareExecuteHRV(Key) synkroniserar fördelningen mellan STRECKREKTANGEL och IckeDito för kommandonycklarna, med vissa förberedelser som streckrektangelns viktiga FORMATERING,

 

{Allmänna villkor · Endast om streckrektangel finns:}

 X:=0; Y:=0; X1:=0; Y1:=0;

 if (Xm0<>Xm1)and(Ym0<>Ym1) then

 begin

  if Xm1>Xm0 then       begin

  X:= Xm0; X1:=Xm1;     end;

  if Xm0>Xm1 then       begin

  X1:=Xm0+1; X:= Xm1;   end;

  if Ym1>Ym0 then       begin

  Y:= Ym0; Y1:=Ym1;     end;

  if Ym0>Ym1 then       begin

  Y1:=Ym0+1; Y:= Ym1;   end;

{Gäller samtliga fall|HIMRV:}

{Slutrektangeln|OPERATIVA STRECKREKTANGELN|LeftTopRightBottom:}

  Rekt:= Rect(X,Y,X1,Y1);

{Denna sista rad tar bort streckrektangeln:}

  Image1.Canvas.Rectangle(Xm0,Ym0,Xm1,Ym1);

...

 end;

 

radering och allmänna BitMap-förberedelser (MarkRectIm1ToIm2) som reducerar återstående operationer till HRV-nycklarna.

— Från PrepareExecuteHRV(Key) skickas de återstående kommandonycklarna vidare till HIMRVdistribution(Image2,Key),

 

             case Key of

             Ord('H'): ExecuteHRV(SourceIm,Key);

             Ord('V'): ExecuteHRV(SourceIm,Key);

             Ord('R'): ExecuteHRV(SourceIm,Key);

             end;{endCase}

 

med en inkluderad förberedelse för den mera sammansatta Merge-operationen|KeyM

[särskild BIM-bitmap BIM.Assign(Image2.Picture);] som styrs av NumPad ±-UppNer-räkningarna samt bildflytten Ctrl+Pilar.

— ÅTERSTODEN kommandonyclar HRV verställer sedan sina operationer på

ExecuteHRV(SourceIm: TImage; var Key: Word);:

 

·         FlipVertical

·         FlipHorizontal

·         FlipRGBtoBGR — samma men förenklad kod som FlipHorizontal

·         Rotate90°

med den viktiga och avgörande gemensamma slutformen för flytbildens preparering och visning,

 

·         Procedure BitmapToIm(B: TBitmap);:

 

    Procedure BitmapToIm(B: TBitmap);

    begin with Form1 do begin

             Image2.Picture.Assign(B);

             Image3.Picture.Assign(B);

             Panel5.Caption:=IntToStr(Image2.Width)

             +';'+IntToStr(Image2.Height);

             {Anger bildmåttet, PanelLabeln överst i mitten.}

             {X0:=0; Y0:=0;

             {PlaceLeftTopAt0;0 om använt.}

             CRs:= Image2.ClientRect;

             CRd:=CRs;

{CENTRERA ROTERAT:}

             if S='ScanRotCompleted' then

             begin

              {För rotationerna (RoteraCentrerat):}

              X0:= X0+(CRs.Bottom-CRs.Right)div 2;

              Y0:= Y0+(CRs.Right-CRs.Bottom)div 2; S:='';

             end;

{VERKSTÄLL FLYTBILDEN:}

             OffsetRect(CRd,X0,Y0);

             {PlaceLeftTopAtX0;Y0.}

             Image3.Canvas.CopyRect(CRs, Image1.Canvas,CRd);

             Image1.Canvas.CopyMode := cmSrcCopy;

             Image1.Canvas.CopyRect(CRd, Image2.Canvas,CRs);

    end;{endWithForm1}

    end;{endBitmapToIm}

 

Övriga flytbildsoperationer (Ctrl+Pilar, Duplicate, Merge) som inte direkt använder ovanstående, är av liknande (mindre sammansatt) typ.

 

H                     vändHorisontellt

V                     vänd Vertikalt

R                     Rotera i steg om +90°

Space+H           färgvänd RGB till BGR (»MånskensFärger» blir »SolUppgångsDito» och v.v.)

 

 

PrepareExecuteHRV(Key): Från föreg. anteckningar via T2014:

{STRECKREKTANGEL SAKNAS:}

 begin

  case Key of

   Ord('C'):

   begin

{Original:}

    if CRsEmpty then exit;

    ClipBoard.Assign(Image2.Picture);

{Ctrl+C utan streckrektangel=CopyFleetToClip.}

   end;

{InvertFlipDirect:}

   Ord('D'),Ord('H'),Ord('I'),Ord('R'),Ord('V'):

   begin

    {Test if Image2 has picture:}

    X:=0;

    B:=TBitmap.Create;

    try

     B.Assign(Image2.Picture);

     if B.Empty then X:=-1

    finally

     B.Free;

    end;

    if(X=-1)then exit;

{NoFleet·AppliesToAllKeys.}

{DUPLICATEdirect:}

    if Key=Ord('D') then

    begin

      CRd:= Image2.ClientRect;

      CRs:= CRd;

      CRsEmpty:=False;

      OffsetRect(CRs,X0,Y0);

{*}

      Image3.Canvas.CopyRect(CRd,Image1.Canvas,CRs);

{Vid nästa utläggIm1 läggs FlytKopian på från Im3=bevaras påIm1.}

{*}   {Om också Ctrl+D = TaBortUndre|FöreOvan|StreckRekt

       måste finnas:

       Image1.Canvas.Brush.Color:= clWhite;

       Image1.Canvas.FillRect(CRs);}

      exit;

    end;

    {Återställer Image1|Förbereder för kommande resultat:}

    Image1.Canvas.CopyMode := cmSrcCopy;

    Image1.Canvas.CopyRect(CRd,Image3.Canvas,CRs);

    CRs:= Image2.ClientRect;

    CRd:= CRs;

    {CRd/s vilketsom kan användas för Objektet.}

    {Resten sköts på InvertFlip|HIMRVdistribution:}

    HIMRVdistribution(Image2,Key);

   end;{endDHIRV}

  end;{endCaseKeyNoMarkRect}

 end;{endNoMarkRect}

 

 

Nedanstående har här i efterhand justerats med nya rutiner (TMemoryStream — samma exekveringshastighet [om möjligt något snabbare]) i samband med upptäckten av 16;64-felet.

 

 

{VÄND  H|ORISONTELLT  V|ERTIKALT  R|OTERAi+90°-steg:}

Procedure TForm1.ExecuteHRV(SourceIm: TImage; Key: Word);

var

  x,y,y3,s:Integer;

  A,B :    TBitMap;

  Pa,Pb:   PBytearray;

  H,W,Z,E: Integer;

  R:       TRect;

begin

  A:= TBitMap.Create;

  B:= TBitMap.Create;

  try

    BitMapRect(CRs,A);

    BitMapRect(CRs,B);

    A.Canvas.CopyRect(CRd,SourceIm.Canvas,CRs);

    {SourceIm är Im1 vid MarkRect, annars (i allmänhet) Im2.}

    A.PixelFormat:= pf32bit;

    B.PixelFormat:= pf32bit;

{KEYS:}

case Key of

Ord('I'): begin

{INVERT|I: — denna rutin finns redan ordnad via

det enklare WindowsAPI med CopyMode cmDestInvert:}

    W:= A.Width -1;

    H:= A.Height-1;

    for y:= 0 to H do

    begin

      Pa:= A.ScanLine[y];

      Pb:= B.ScanLine[y];

      for x:= 0 to W  do

      begin

       {Sista Byten överhoppas alltid(RGBQuadStandard):}

       Pb[4*x+0]:= 255-Pa[4*x+0];

       Pb[4*x+1]:= 255-Pa[4*x+1];

       Pb[4*x+2]:= 255-Pa[4*x+2];

       {Om första byten överhoppas ersätts svart med blått.}

      end;{endForX}

    end;{endForY}

     end;{end|I}

Ord('H'): begin

UTGÅR på grund av 16;64-felet: ..................................................................................................................................... :

{FLIP HORIZONTAL|H|Space+H:}

    if GetKeyState(VK_SPACE)<0 then E:=1 else E:=0;

  {ReverseradPalett: Tryck Space+H.}

    W:= A.Width-1;

    H:= A.Height-1;

    Z:= 4*W;

    for y:= 0 to H do

    begin

      Pa:= A.ScanLine[y];

      Pb:= B.ScanLine[y];

      for x:= 0 to W  do

      begin

        s:= 4*x;

        Pb[(1-E)*Z + (2*E-1)*s + 0]:= Pa[s + (1-E)*0 + E*2];

        Pb[(1-E)*Z + (2*E-1)*s + 1]:= Pa[s + 1];

        Pb[(1-E)*Z + (2*E-1)*s + 2]:= Pa[s + (1-E)*2 + E*0];

      end;{endForX}

      {SPACE+H ger färgvändningen R|G|B till B|G|R}

    end;{endForY}

UTGÅR på grund av 16;64-felet: ..................................................................................................................................... .

     end;{end|H}

Ord('V'): begin

{FLIP VERTICAL|:}

    W:= 4*(A.Width);

    H:= A.Height-1;

    for y:= 0 to H do

    begin

      Pa:= A.ScanLine[y];

      Pb:= B.ScanLine[H-y];

      for x:= 0 to W-1  do

      Pb[x]:= Pa[x];

    end;{endForY}

    Image1.Canvas.CopyMode:= cmSrcCopy;

     end;{end|V}

Ord('R'): begin

UTGÅR på grund av 16;64-felet: ..................................................................................................................................... :

{ROTATE|R|RotCentrum=RektMitt:}

    W:= A.Width -1;

    H:= A.Height-1;

    for y:=0 to H do

    begin

      Pa:= A.ScanLine[y];

      y3:= 4*y;

      for x:=0 to W do

      begin

        Pb:= B.ScanLine[W-x];

        Pb[y3+2]:= Pa[4*x+2];

        Pb[y3+1]:= Pa[4*x+1];

        Pb[y3+0]:= Pa[4*x+0];

      end;{endForX}

    end;{endForY}

    S:='ScanRotCompleted';

UTGÅR på grund av 16;64-felet: ..................................................................................................................................... .

     end;{end|R}

end;{endCaseKey} 

 

{ALLA|FlytbildsPreparering:}

    BitmapToIm(B);

  finally

    A.free;

    B.Free;

  end;

end; {Invert32BitTest}

Visst:

— Vi testar sedan en i taget av ovanstående.

BitMapToIm förbereder och verkställer den slutliga resultatutläggningen på Im1 genom att avstämma aktuella rektanglar och utföra korrekta kopieringar.

 

Procedure TForm1.BitMapToIm(B: TBitmap);

begin

         Image2.Picture.Assign(B);

         Image3.Picture.Assign(B);

         Panel5.Caption:=IntToStr(Image2.Width)

         +';'+IntToStr(Image2.Height);

         {Anger bildmåttet, PanelLabeln överst i mitten.}

         CRs:= Image2.ClientRect;

         CRd:=CRs;

 

      if S='ScanRotCompleted' then begin

      {För 90°-rotationerna (RoteraCentrerat):}

      X0:= X0+(CRs.Bottom-CRs.Right)div 2;

      Y0:= Y0+(CRs.Right-CRs.Bottom)div 2;

      S:='';

      end;

 

{PlaceLeftTopAtX0;Y0:}

         OffsetRect(CRd,X0,Y0);

{VISA RESULTAT:}

         Image3.Canvas.CopyRect(CRs, Image1.Canvas,CRd);

         Image1.Canvas.CopyMode := cmSrcCopy;

         Image1.Canvas.CopyRect(CRd, Image2.Canvas,CRs);

end;{endBitmapToIm}

 

 

 

 

Zoom:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

k = (% · INT[1/%])·2 = superSamplingRatio → + Anti-Aliasing (AverageByPercent):

k/(2·INT) = %:

U = 2·INT:

Vi delar upp hela bilden i en vertikal del och en horisontell del för att få optimal bildändringsfunktion:

 

10Nov2014:

— Ännu en (galant) enklare lösning har visat sig:

— Experiment med ovanstående visade strax följande:

— Anti-Aliasing-tillskottet KAN UNDVARAS HELT om man bara utför en SUPER SAMPLING-rutin med enhetsförstoringar, mellanliggande normal %-justering, och efterföljande FF-förminskning enligt följande algoritm:

 

1. utgå från en zF-enhetsförstorad originalkopia (StrecthDraw);

— Ju större zF-värde, desto bättre, men vi måste begränsa värdet eftersom datorn tar allt längre tid på sig att RENDERA (beroende på inställningar): ett zF=10 har här satts som gräns, med zF-autoJusatering till max3 för 23-tumsSkärmen bild: zF=3 betyder då att zoomen arbetar på en 3^2=9ggr förstorad arbetskopia = ca 2Mb·9 =grovt 20Mb.

— Det tar TID (här INOM en sekund, vilket har bestämt gränsen med dagens datorprestanda).

2. Justera FÖRMINSKNINGEN (förstoringar innefattas inte här) regelrätt procentuellt (också via StrechDraw igen, men nu på föregående storkopia) i resp x|y-led (X= zW; Y=zH):

3. HeltalsFörminska sedan slutligen resultatet från 2 med zF i FF-metoden.

 

Resultatet i netto blir alldeles detsamma som att från skala 1:1 minska originalbilden med respektive zW;zH:

 

(zF·W0·[zW/W0] ; zF·H0·[zH/H0])

=

(zF·W0·[zW/W0] ; zF·H0·[zH/H0])

=

(zF·     [zW]      ; zF·     [zH])

;

(zF·     [zW]      ; zF·     [zH])/zF

=

(           [zW]      ;          [zH])

 

— Inget mer. Inget mindre.

— Helt enastående resultat.

— Genom att ändra zF kan vi direkt se hur kvaliteten ändras med växande zF.

— Separat tillägg ger möjlighet att lägga till Anti-Alias separat.

 

TANGENTER

Z                     ZoomOn|Off

F                     zF aktiverad: pilUppNer stegar 1-10, display visar:
zF-värdet anger originalbildens förstoring som arbetskopia: ju högre värde, desto högre kvalitet i förminskningar — och desto längre TID för RENDERING: avgränsningar har här gjorts som begränsar renderingstiden till MAX 1(/5) sekund — på bekostnad att zF autoavgränsas om originalbilden är STOR [typ större än en 23 tums bildskärm, eller runt 2MByte bildpixels i 32 bitarsSystem]: för 23-tumsbilden är zF max = 3 [=ca 18MB=2·3²].

A                     Average aktiverad: pilUppNer stegar 0,1-1,0, display visar

R                     Range aktiverad: pilUppNer stegar 1-20, display visar;
A|R reglerar Anti-Aliasing (grad av oskärpa):
Average reglerar styrkan: 1=inget, 0 max (standard = 0,6);
Range reglerar pixelomfattningen (R+1)^2=antalet pixels som Anti-Aliasingen omfattar i bildpixelkvadraten, R=max20=400 pixels/pixel (standard = 1 = 4 pixels/pixel).

Ctrl+                PilHöger|Vänster, Ökar|Minskar horisontellt

Ctrl+                PilUpp|Ner, Ökar|Minskar vertikalt

Ctrl+                NumPad 1 2 3 4, sätter steglängden 1 5 20 100 till ovan|nedan

Ctrl+                Shift+PilUpp|Ner, Ökar|Minskar proportionell zoom av originalet

PageUp             Heltalsförstoring

PageDown         Heltalsförminskning

Ctrl+                Numpad|+, entydigt PageUp

Ctrl+                Numpad|–, entydigt PageDown

Ctrl+                P, reverserar PageUp|Dn

Ctrl+                M, reverserar piltangenterna

 

Tangenterna kan hållas nedtryckta, resultatet visar sig så snabbt datorn hinner med (max ca 1/5 sekund per resultat [originalbild från 23 tums skärmbild] med datorstandard 2010).

— Speciellt för PROCENTUELLA zoomningar: LÄS AV STATUSDISPLAYEN nederst på aktuellt värde: Håll ner resp. tangenter tills önskat värde visar sig: Procentvärdena anges med tre decimalers noggrannhet.

   Ett avgörande argument:

— När vi arbetar (upprepat) med bilder vill vi INTE hålla på att ställa in SAMMA zoomparametrar för varje gång vi tar in en ny bild:

 

— Vi VILL att senast använda ska gälla tills ändrat — för att snabbt kunna använda en viss inställning på en serie bilder (i samband med typ fotografisk redigering, från givna original typ Fotovisare (ny bild med typ PilHöger) eller annat [PrintScreen]).

 

— Paint.NET, gratisprogram för privat bruk — här till viss utomordentlig jämförelse — har en bra (högkvalitativ) zoom-funktion, som dessvärre INTE kommer ihåg senaste inställningen. Det blir jobbigt att ställa in samma om och om igen. ZoomProgrammet här minns senaste.

— Jämför även zoomfunktionen i Windows Paint (Windows 7):

— Man undrar stillsamt vad exakt programmakarna MENAR med den typen?

   Rent ut sagt: rena rama skiten. Exempel:

 

 

 

 

Sedan man exakt samma markering dragit några gånger i Microsofts ÄndraStorleksSnöre i Paint Windows 7, blir resultatet som närmast ovan, originalet över.

— Ursäkta: vafan ska man HA Det till?

— Vad ska det användas för?

(Improviserad grafisk översättning från Engelska till Arabiska).

 

Zoom — Z

Z On|Off — Steglängd Ctrl+ NumPad 1 2 3 4 = 1 5 20 100 pixels;

Ctrl+ PilHö|Vä Öka|Minska HORISONTELLT; PilUp|Dn Öka|Minska VERTIKALT;

Ctrl+Shift+PilUp|Dn Öka|Minska PROPORTIONELL zoom; PageUp|Dn, HELTAL¦sför- Stora|Minska,

Ctrl+ P¦M reverserar riktningen hos PageUp|Dn ¦ Piltang.

 S  aktiverar|avaktiverar R och A, nedan:

F R A + PilUp|Dn aktiverar och ändrar KVALITETSFAKTOR (F|1-10 stand. 3),  Område (R|1-20 stand. 1),

Oskärpa (A|0,0-1,0 stand. 0,6)

———————————————————————————————————————————

STATUSRADEN NEDERST VISAR AKTUELLA VÄRDEN

 

 

SLUTFORMEN: endast heltal för ZoomOut U:

Vertikalt separat via TMemoryStream|GeneralZoom:

Pa originalbilden

Pq förminskningen

 

Paint.NET — gratis fotoredigeringsprogram för privata användare — har i BestQuality en zoomfunktion som nära ansluter till »flygfotometoden» (min egen utformning från Delphi1 [1997]): heltalsförminskningar 2 3 4 5 ... som tar kvadratmedelvärdet av 4 9 16 25 ... pixels som sätts på resultatbildpixlarna 1 2 3 4 ...

 

Exempel, originalet vänster, förminskning 2ggr höger:

 

 

 

Det motsvarar (vad vi vet) den mesta möjliga zoomOUTkvalitet som kan fås:

— inga egentliga bildförluster förekommer; alla bildpixels är representerade.

 

NÄRA SAMMA kvalitet kan fås för alla mellanliggande [mellan n och n+1] förminskningsgrader enligt följande algoritm:

 

originalbilden sträcks (med StrecthDraw) ut så mycket som krävs för att sedan via en dubblerad förminskning via »flygfotometoden» få den önskade förminskningen.

 

EXEMPEL, kvadratiskt:

— En bild önskas förminskad från 100% till 18%: Vi räknar ut en SuperSamplingRatio (StrecthDraw-värde) enligt

 

k = (% · INT[1/%])·2 = superSamplingRatio     ;

;

INT(1/0,18)      = 5                                             ;

0,18 · 5              = 0,9                                          ; k/2

0,9 · 2                = 1,8                                          ; SuperSamplingRatio

 

Originalbilden ska alltså sträckas ut 180% (alltid mellan 100 till 200%),

 

 

därefter påföras lämplig Anti-Aliasing (jämnar ut fula ojämnheter i slutresultatet),

 

 

och sedan förminskas via flygfoto-metoden (FF) 5·2=10ggr; 1,8/10=0,18:

 

(Slutresultatet ovan innefattar »automatisk avståndsuttoning»).

— Jämför kvaliteten direkt med 5ggr FF-förminskning (till 20%):

 

 

 

Se även nedan i HastighetstestZoom.

Saken kompliceras (något) av att vi nu måste dela upp ovanstående kvadratiska exempel för samtliga fall i en vertikal del och en horisontell del, för bekvämligheten att få fram alla möjliga plangeometriska bildändringar, inte enbart xy-ändringar med bevarad originalproportion.

 

Strategi:

Zooma Kvadratiskt = originalets xy-proportioner intakta:

1. Ren StretchDraw — gäller före nedan (2) med Z>1 i vilket x&y-fall

2. FF-metoden — gäller Z<1:

a. direkt för heltal 1/z

b. med SuperSampling och Anti-Aliasing för alla mellan

 

Zooma Rektangulärt = originalets xy-proportioner ändrade:

1. Ren StretchDraw — gäller före nedan (2) med Z>1 i vilket x|y-fall

2. FF-metoden — gäller Z<1:

a. direkt om Z<1 motsv heltalsdelning

b. gen. med SuperSampling och Anti-Aliasing för alla mellan

 

Enklare:

 

Förstoras originalbilden (Z>1) i x|y gäller i vilket fall StretchDraw i resp. x|y

(möjlighet finns att lägga till Anti-Aliasing separat);

Övriga fall:

Förekommer någon förminskning (Z<1) i x|y gäller FF-metoden för resp. x|y:

1. StretchDraw = SuperSampling [k = (% · INT[1/%])·2 = superSamplingRatio]

2. Anti-Aliasing (Range=1=2×2pixels; Average=0,6 [efter särskild utprovning])

3. FF-metoden (Z=2·INT)

 

För att få reda på vad som gäller i vilket fall, behöver vi endast undersöka originalbildens ÄNDRADE x|y-värden:

— Vi anställer DELS zoomningen via PageUp|Dn med heltalszoomningar (1 2 3 ..), och DELS via diskreta ändringar i steg om 1 pixel (som vi kan ändra till steg om 5 eller 10 eller 50 pixels) för respektive x och y via piltangenter Up|Dn för y och Hö|Vä för x — samt kanske en del med möjlighet att ange procentuella ändringstal [in till 1/1000 — 23-tumsskärmen typ];

 

Är x>x0 verkställs x(StretchDraw)

Är y>y0 verkställs y(StretchDraw)

 

 

 

 

HastighetstestZoom:

 

Hela bildskärmen 23tum hastighetstest (4Nov2014) — exakt samma bildresultat:

Vertikal förminskning U=2ggr med ScanLine-metoden Delphi4:

0,843 Se3kunder.

;

Vertikal förminskning U=2ggr med TMemoryStream-metoden Delphi4:

0,063 Sekunder.

;

TMemoryStream-metoden är 843/63 = 14,05 ggr snabbare än ScanLine-metoden

 

Tidsvärden i ett första enstaka testfall: tiderna varierar sedan något beroende på datorns olika upptagenhet.

 

 

Kodblocken (centraldelarna) ned i VertSLtest och VertTMStest.

VertSLtest:

ScanLine Vertical

Programkoden, centralblocket, för ScanLine-metoden

— BMP global bitmap håller flytbilden Image2 som ska förminskas, resultatet på lokal bitmap A, separata rutiner:

 

...

Gtc:= GetTickCount;

           try

{MÅLBILDEN|Originalet i skala 1:1¦: förstorade B(från A)överförs förminskad till A:}

            BitmapRect(tR,A);

            A.PixelFormat:= pf32bit;

            A.Canvas.Brush.Color:= clWhite;

            A.Canvas.FillRect(tR);

              for y:=0 to aH-1 do begin

                Pa:= A.ScanLine[y+0];       //Målet|

                for x:= 0 to W-1 do begin

                 R:= 0;

                 G:= 0;

                 B:= 0;

                 for S:= 0 to U-1 do begin

                  Pb:= BMP.ScanLine[U*y+S]; //Källan|

                  R:= R + Pb[4*x+2];

                  G:= G + Pb[4*x+1];

                  B:= B + Pb[4*x+0];

                 end;{endWithS}

                 Pa[4*x+2]:= R div U;

                 Pa[4*x+1]:= G div U;

                 Pa[4*x+0]:= B div U;

                end;{endForX}

              end;{endForY}

              Image1.Canvas.Draw(0,0,A);

           finally

            A.Free;

           end;

Label1.Caption:= IntToStr(GetTickCount - Gtc);

843mS

 

End VertSLtest.

 

VertTMStest:

TMemoryStream Vertical

 

Programkoden, centralblocket, för TMemoryStream-metoden

originalet:          bA(bitmap), Pa(PChar)

förminskningen   bQ(bitmap), Pq(PChar)

separata rutiner

 

 

...

Gtc:= GetTickCount;

          try

             {SpecialRutin, etablerar bitmap:ens dimensioner:}

             BitmapRect(tA,bA);

             BitmapRect(tQ,bQ);

{PREPARERA MÅLBILDENS BITMAP FÖR BAKGRUNDSELIMINERING:}

             bA.Canvas.Brush.Color:= clWhite;

             bA.Canvas.FillRect(tA);

             bQ.Canvas.Brush.Color:= clWhite;

             bQ.Canvas.FillRect(tQ);

             {Preparera|BehandlingsBitMaps:}

             bA.PixelFormat:= pf32bit;

             bQ.PixelFormat:= pf32bit;

             {Källbilden|Im2¦Copy|bA¦:}

             bA.Canvas.CopyRect(tA,Image2.Canvas,tA);

             {SPARA TILL MemoryStreamen så att vi kan göra ändringar därifrån:}

             bA.SaveToStream(TMa); //Källbilden|FlytBildeIm2.

             bQ.SaveToStream(TMq); //Målbilden|.

{TILLDELNING MemoryStreamen tilldelas en AdressPekare = BörjaHärifrån:}

             Pa:= TMa.Memory;      //1:st byte

             Pq:= TMq.Memory;      //1:st byte

             {Samma som hela BMP-strukturen|Med BitMapInfoHeader: börjar från pos54:}

             for y:= 0 to Hq-1 do begin

                       {Målbildens pixelposition i dataminnet:}

                        Q:= Pq + 54 + 4*((Hq -(y      ))*W);

                for x:= 0 to W-1 do begin

                   R:= 0;

                   G:= 0;

                   B:= 0;

                   for S:= 0 to U-1 do begin

                       {Källbildens pixelposition i dataminnet:}

                        A:= Pa + 54 + 4*((H-1-(y*U + S))*W);

                        R:= R + Byte((A + 4*x +2)^);

                        G:= G + Byte((A + 4*x +1)^);

                        B:= B + Byte((A + 4*x +0)^);

                   end;{endForS}

                   {TA UT MEDELVÄRDET I y-gruppen = UtZoomade Bilden:}

                   Byte((Q + 4*x +2)^):= R div U;

                   Byte((Q + 4*x +1)^):= G div U;

                   Byte((Q + 4*x +0)^):= B div U;

                end;{endForX}

             end;{endForY}

{FINALIZING:}

             {Förbered MemoryTillBitMap:}

             {Börjar från MinnesPekarensPosition - funkar inte om annat än från 0:}

             TMq.Position:= 0;

{UPPDATERAR ÄNDRINGARNA:}

             bQ.LoadFromStream(TMq);

{FlytbildsPreparering|OK|Bilden ritas ut:}

             Image1.Canvas.Draw(0,0,bQ);

          finally

             bA.Free;

             bQ.Free;

             TMq.Free;

          end;

Label1.Caption:= IntToStr(GetTickCount - Gtc);

63mS

 

End VertTMStest.

 

 

 

Zoomfunktionerna i P2

Inga särskilda komponenter behövs:

Ren programkod på befintlig bildyta:

 

 

21Sep2014|Unit1A P2¦Procedure StretchDrawIm2(Key,Shift):

 

 

 

 

 

 

ZoomDISPLAYEN i P2 med dess olika statusINFO (21Sep2014).

 

Esc             ZoomOff | se även Ctrl+Z nedan

Z                 ZoomOn:

Z                 ZoomStretch OnOff: Off=StretchDraw=BasicQuality ¦ ON=EnhancedQ


Med ZoomStretchON visas ovanstående mera sammansatta statusdisplay:
Av¦Ra¦Z med efterföljande värden betyder Average¦Range¦qualityZoom:
Average 1-0 styr diffusheten (som minimerar skillnader i uttoningar),
Range styr antalet kvadratpixels som Average arbetar på, 1¦3²=9; 2¦4²=16; 3¦5²=25; osv. ända upp till 20²=400 (som ger typ skuggeffekter);
Z, se NP 2 nedan.
Tangent A|R kanaliserar och PilUppNer räknar; resultaten visas omedelbart.
— STARTLÄGE: Eftersom ZoomStretchON helt saknar verkan med heltalsförstoringar >1 (från 2 och uppåt), samt att OM ON-läget ändå är valt (Z) det bara tar (mycket) längre tid för resultatet att visa sig, finns en AutoReglerare som kopplar bort ZoomStretchON med ZoomUnit>1, och AutoÅterställer för övrigt OM ZoomStretchON är valt. Därmed slipper vi ifrån de onödiga fördröjningarna om vi vill ha speciellt STORA förstoringar [Tillagt 4Okt2014 via cZR Unit1A ZoomGeneral].

S                 ZoomSquare OnOff: Off=ZoomRect, On=ZoomSquare

NumPad     2 — växlar mellan något olika kvaliteter på zoomningar i området förstoring 1 till 2 ggr och från 1 och neråt:
lägre kvaliteten (displayvärde 2) med ett fördubblat specialpreparerat original;
(något) högre kvaliteten med fyrdubbla dito (displayvärde 4).

Ctrl+M        Pilvändare, reverserar piltangenternas funktionsriktning

Ctrl+P         PageIUpDnVändare, reverserar UpDn-funktionsriktningen

PageUp      Samma som S-funktionen men förstoring enbart i heltal

PageDn      Samma som S-funktionen men förminskning enbart i reciproka heltal

Ctrl+NP      ± Samma som PageUpDn men utan pilreversering: + större — mindre;
Ingen övre zoomIN-gräns finns (datorns prestanda sätter gränsen):
ZoomStretchON tar längre tid för stora bilder, medan Off-läget går betydligt snabbare: för förstoringar från 2 och uppåt har ZoomStretchON i gengäld ingen egentlig inverkan: den kan helt frånkopplas för dessa fall med en resulterande snabbare (ögonblicklig) respons;
Undre zoomgränsen har här satts till en bild med bredden|höjden 1 pixel.

Ctrl+NP      1 2 3 = Stegintervall i pixelsteg 1 5 20

Ctrl+C        Kopierar senaste zoombilden till Urklipp

Ctrl+            Z, samma som Ctrl+C men med samtidig avslutning av zoomläget;
Läget före ZoomOn sparas alltid och man kommer tillbaka dit efter Zoomningen, inkluderat ev. tidigare befintlig flytbild.

 

Pil- och PageREVERSERINGEN

— För att göra det maximalt bekvämt:

— BEROENDE PÅ VANA vill en del av oss ha BETYDELSERNA »UPP NER FRAMÅT BAKÅT» stundtals omkastade, allt efter vana, behov, intryck, bekvämlighet.

— Det görs här med två olika optioner:

Ctrl+P växlar riktning för PageUpDn-funktionerna i Zoom;

Ctrl+M växlar riktning för Pil-funktionerna i Zoom.

 

ZoomFunktionen tar källbilden direkt från aktuell Flytbild (Im2) eller via separat streckrektangel;

— Under ZoomOperationerna sparas bildfönstret med alla inställningar, och läggs sedan tillbaka efter Ctrl+Z nr2 = CloseZoom.

 

Resultaten visas i Statusraden nederst med rektangelmått, procentuella värden, och valda sätt.

— SPECIELLT Z-tillvalet har nu (äntligen) medgett en heltäckande »hyfsat allmän kvalitativ» zoomRepresentation genomgående. Resultaten speciellt mellan skala 1:1 och 2:1 (dubblering) och mellan 1:1 och 1:2 (halvering) innehåller de mest åtråvärda delarna i datorzoomningar (som det har visat sig) — och som också avslöjar vilken zoomteknik som används.

— Här har den (nästan) allra enklaste av alla metoder används:

— Zoomningen för icke heltaliga värden använder en kombination av det enkla snabba Windows API-stödda StretchDraw — alla pixels bara rådras — och en medelvärdesbildande »flygfotozoomning». Slutresultatet KAN bli bättre, men får tills vidare duga.

— Webben (2014) innehåller f.ö. en hel del PDF-beskrivningar på Zooming Technique, väl utanför den här framställningens ramar.

 

TypExempel — Vä: Källbild; Mitten: Halverad med StretchDraw; : samma men med Z-funktionen beskriven ovan:

                       

 

 

S-funktionen med Ctrl+Pilar ökar eller minskar Källbilden i pixelsteg som KVADRAT från källbildens största utsträckning. Dvs., S-funktionen verkställer en reguljär pixelbaserad förstoring/förminskning; separat statusinfo visar motsvarande %-värden.

 

Beskrivning

Elementär flytbildsteknik — grundexempel i DELPHI4

DAGENS DATORPROGRAM har (min mening) en (ytterst FUL OVANA att INTE utnyttja PILTANGENTER:

— Programmakarna vill tydligen att MUSEN ska spela rollen av allt möjligt i underjorden: flytta bilder, välja verktyg, peka och påta generellt.

 

ZOOMFUNKTIONER är ett bra exempel — till exempel (WindowsStandard) i Paint.

— Enda sättet (min erfarenhet) att ha PRECIS KOLL på zoomning är att zoomning KAN göras med piltangenter samt integrerat att

 

·         källbildens mått visas

·         den zoomade källbildens mått visas

·         zoomningens procentuella andelar visas

·         zoomningen via piltangenterna kan ställas in i stegintervall (här 1 5 20 pixels med Ctrl+NumPad 1 2 3) för snabba eller exakta positioner och värden

 

Paint i Windows som jämförande exempel visar källbildens mått — som ändras när man drar i streckrektangelns hörn eller kanter; procentuella värden kan skrivas in via separat dialogruta (via högerklickspanel med tillval). Men som vanligt i Paint finns inte piltangenterna med i bilden: dessa svarar inte, står funktionslösa (om inte aktiverade på omständligt sätt via HjälpCenter [som sedan måste ställas om tillbaka på samma omständliga sätt]: HandikappHjälpmedel med enStegsPixelFunktion). En del besitter speciell förmåga att döda datoranvändningen.

 

ZoomFunktionen i P2 har försökt avhjälpa alla brister för att få fram snabba, exakta, resultat.

— Musen är inte mycket till hjälp här utom för att dra upp en streckrektangel.

   Jämför STRECKREKTANGELN som sådan MED musflyttningsfunktion:

   Streckrektangeln (i [enklare] kommersiella ritprogram) måste ALLTID avställas med någon separat kommadoform (Esc eller Ctrl+R, MusVäKlick, eller något) — i Paint speciellt DESSUTOM MED »tillbörlig distans» mellan Peken och StreckRektangeln om avklickning ska ske med MusVä: Man kan i Paint t.ex. inte klicka med Peken mitt i — vilket bara betyder ytterligare besvär.

— Här i P2 försvinner ALLTID streckrektangeln MED den operation den avser att betjäna (Ctrl+C|D|X|Z ...) — eller om man ångrar sig sedan märkrektangeln ritats, radera den med MusVäKJlick eller ESCape.

   I den operativa hanteringen i P2 finns ALDRIG — eller ska inte finnas — rester efter någon operation.

 

 

 

 

WriteText

Ctrl+T              teckensnitten i lista med storleksruta (Tab): fäll nerUpp listan med Alt+PilNer|Upp

Enter                verkställer valt teckensnitt

Tab                   hoppar till teckensnittsstorleksrutan

Enter                no2 (från teckenstorleksrutan) gömmer teckensnittspanelen och tar fram inskrivningsboxen

Enter                no3 lägger ut texten slutligt som flytbild vid PekPositionen [Ctrl+Pilar flyttar]

                         Fetstil, Kursiverat, Stora, Små bokstäver ges i inskrivningsboxen med Alt+F|K|O|L

T                       Successiva texter: Senaste teckensnitt, storlek, färg och text nås direkt med T för successivt nya objekt; verkställ med Enter

X | Insert         Textfärg sätts före T|Ctrl+T med tangent X alt. Shift+T eller Shift+Insert, eller vid textredigeringen direkt med INSERT som verkställer FärgenUnderPeken (F4 tar fram en enklare RGB-palett som kan användas) — Alt+Pilar presicionsplacerar Peken i läge TextRed.

 

 

 

WriteText

Ctrl+T              listar teckensnitt, storleksruta (Tab): Alt+PilNer|Upp

Enter                verkställer valt teckensnitt

Tab                   hoppar till teckensnittsstorleksrutan

Enter                [no2] gömmer tar fram inskrivningsboxen

Enter                [no3] lägger ut texten som flytbild vid PekPositionen

Alt+ L O E F K    Liten Stor FetKursiv Fet Kursiv

T                       Successiva texter: Senaste teckensnitt, storlek, färg och text
nås direkt med T för successivt nya objekt; verkställ med Enter

X | Insert         Textfärg sätts före T|Ctrl+T med tangent X alt. Shift+T eller
Shift+Insert, eller direkt med INSERT FärgenUnderPeken

Alt+Pilar          precisionsplacerar Peken för exakt färgval i läge TextRedigering

 

 

 

 

WriteText:

Elementär flytbildsteknik — grundexempel i DELPHI4

 

WriteText — Text på bild

Komponenterna som krävs:

0. En PANEL (här Panel36|från andra programutvecklingar, min bekvämlighet) att sätta alla WriteText-komponenterna på för bekväm visning|gömning;

1. En ComboBox som laddas med datorns alla teckensnitt vid uppstart (ComboBox1.Items:= Screen.Fonts;);

Alt+PilNer fäller ner ComboBoxens MenyLista där alla teckensnittsnamnen står;

— För att t.ex. komma till Times New Roman, tryck T och första T-förekomsten visas (rulla sedan neråt med PilNer).

— I startläget öppnas ComboBoxen lämpligast med menyrullen nedfälld så att man ser listningen;

2. En EditBox (här Edit16|från andra programutvecklingar, min bekvämlighet) för TeckenStorlek;

— Sedan man valt teckensnittet med ett första Enter når man TeckenStorleksBoxen med en Tab (eller klicka för att flytta fokus till teckenstorleksrutan); mata in värdet, sedan Enter igen och teckensnittspanelen försvinner, och själva »SkrivInDinText-box»:en kommer fram — i fortsättningen för vidare behöver man sedan bara trycka T för att få fram den delen med sist inmatade text: utskriften hamnar i slutänden ALLTID där peken står, och den ges då som FLYTBILD.

3. En separat TextBox (här Edit6|från andra programutvecklingar, min bekvämlighet):

— Man kan redigera texten under inmatning, flytta position där texten ska stå — uppdateras för varje tangentnedtryckning — och om så önskas återgår till annat teckensnitt och|eller storlek med Ctrl+T och Enter|Tab|Enter:

— Alt+ Tangenterna L O E F K N   styr teckensnittet:

L      liten bokstav för alla markerade

O      stor bokstav för alla markerade

E      växlar fet kursiv | normal

F      växlar fet          | normal

K      växlar kursiv      | normal

N      normal              tvingar alltid normal

Textfärg [FärgDisplay]

 

Notera att DESIGNEN på de olika komponenterna i P2-projektet — här — ÄNDRAR UTSEENDE allteftersom jag själv begåvas med olika uppslag under utvecklingsarbetet för att pröva olika sätt och försöka känna efter vad som verkar mest lämpligt = MINST STÖRANDE för helhetens användning: FÄRGER är jättekul — men har en tendens att dra till sig mer uppmärksamhet än föremålet för arbetet. Gråskalor med vissa smärre färginslag ger bästa intrycket — lugnhet, fokus på arbetsytan.

färgpanelerna ovan med startvärde förgrund fgCol=clBlack(lilla svarta mittrutanÖverst ¦BackGroundColor) bakgrund bgCol=clWhite(omgivande vitrutanÖverst¦ForeGroundColor) teckenfärg (färgen på T:et nedre höger ) — kan sättas efter önskemål enligt tangenterna

textfärg (T): Shift+T | Shift+INSERT | X — färgen under peken antas då och visas i T:et | svart från start

bakgrundsfärg till text | vitt från start | Tangent B — färgen under peken

förgrundsfärg, fristående från text | vitt från start | Tanget N — färgen under peken

—Bakgrund(B)Förgrund(N) kopplar direkt till EditColors (NumPad5): sist aktiverade färg och område gäller för färgredigeringen [se EditColors-panelen].

— För TEXT har endast T:färgen (X|Shift+T|Insert) och bakgrunden (B) betydelse.

(Funktionern med Förgrundsfärgen har ännu så länge ingen direkt tillämpning i P2 | 2Okt2014 — frånsett separat Färganalys med NumPad 5 [EditColors] då man vill veta ordningen RGB|HSB. Förgrundsfärgen ska normalt koppla till olika rit- och färgfyllnadsuppgifter. Men de verktygen finns ännu inte i P2|2Okt2014).

4. En Label (här Label58|från andra programutvecklingar, min bekvämlighet) som rubricerar FontSize — vit text som är transparent (Object Inspector, Transparent = True);

5. En Label (här Label57|från andra programutvecklingar, min bekvämlighet) »VisaTeckensnittet med Färg och Storlek» som visar det valda teckensnittet som det kommer att se ut,

så att man också bekvämt kan undersöka de olika teckensnittens utseenden.

— VERKSTÄLLANDE tangentkommando i P2 är alltid Enter för att få ut texten.

 

Sista Enter.kommandot avslutar EditBoxen och lägger ut texten slutligt där markören står på bildytan.

— DÄREFTER FUNGERAR TEXTEN SOM EN ORDINÄR FLYTBILD: kan vändas, roteras, inverteras, dupliceras, kopieras — men inte åter redigeras.

— För »återredigering», tryck bara T igen och EditBoxen kommer åter med senast använda text och teckensnitt, färg och storlek.

— Mycket bekväm funktion för att t.ex. skriva etiketter i upprepade uppställningar (med bestämda intervall) med VISSA varierande data.

   Se en del exempel på hur (Icke TrueType) text kan manipuleras för att sättas över godtyckliga bakgrunder i BakgrundsOberoende flytbild i Exempel.

 

 

 

 

 

TextIn:

TextIN

 

TextIn är ett programutformat specialverktyg för att få TrueTypeText — »vanlig större text» — att passa ihop tillsammans med godtyckliga bakgrunder med bevarad teckenskärpa.

 

 

Övergångarna mellan textkropparnas raka och vinklade delar innefattar i TrueType-teckensnitten uttoningspixels. Programkoden i TextIn [CentralKoden] anpassar dessa till varje typ av aktuell bakgrund.

 

I P2 kan TextIn kombineras med EditColor (NumPad 5) för direkt färgval för senast inskrivna text och position.

 

Tangent X aktiverar särskilt färgval för TextFärg, med direktkoppling till EditColors för tidsanalog färgredigering.

 

Dvs., man kan precisionsjustera och bestämma TextIn-färg kontinuerligt mot en aktuell (fotografisk) bakgrund: varje ändring i EditColorsPanelen uppdateras omgående i aktuell text.

 

Tangent SPACE togglar TextIn|OnOff

 

 

 

Programfönsterdumpen ovan (7Okt2014) visar ett exempel i P2 under pågående EditColor TextIn-redigering på ett underliggande fotoobjekt.

 

TextIn

Gäller ENDAST direkt efter TrueType WriteText ¦ Ctrl+T, se särskild Info

Texten som flytbild har f.n. begränsad behörighet. Normala bildfunktioner [rotera, invertera, vänd, duplicera, importera, exportera] avställer TextIn automatiskt. Om fortfarande tillgängligt, återuppta med en Space igen.

Space                Aktiverar|Avaktiverar TextInsmältning för senast inskriven text. Texten som flytbild kan flyttas godtyckligt med Ctrl+Pilar. Men TextInsmältningen avställs automatiskt om andra funktioner aktiveras. Återuppta TextIn efter dessa med Space så länge flytobjektet är senast inskriven TrueTypeText.
Speciellt för VIT TEXT:  MoveCopySkipWhite;
— alternerande Space får texten att försvinna|visa sig.
TextInVitText ej reguljär flytbild.
— Med MoveCopyWhite    visas bara den vita tomma textrektangeln.
— För kopior av VitText med TextIn,
kör upprepade T Enter Space.

 

Programsvårigheter TextIn

Programmässig utformning med alla texter enhetligt presentabla från svart till vitt mot godtyckliga bakgrunder kräver att man enhetligt för varje enskilt fall anger bakgrundsfärg (Canvas.Brush.Color) och förgrundsfärg (Canvas. Font.Color).

— Med den ordningen kan alla textfärger med alla bakgrunder fås överförbara »transparent» på alla andra bakgrunder med SkipBackGround (»Tangent W»  i upp- eller »ramläge» = SkipWhite).

— PROBLEMET med TextIn — textsammansmältning med bakgrunden — BLIR i det sammanhanget VIT text:

— Med den (enkla) algoritm som har använts till textIn-blocket i DELPHI4 visar det sig att OM man konsekvent använder ovanstående FörgrundBakgrund-ordning (alla TextInObjekt hamnar som flytbildsobjekt enhetligt på Image2), kvaliteten på speciellt VIT text i vissa bakgrundsfall INTE blir bra: ser bra ut i en viss del av ett underliggande foto, medan rester lämnas om texten går in i en ljusare eller helt vit del. Det ville vi inte ha.

— Försök med att välja svart bakgrund för den vita texten ger i stort sett samma mindre tillfredsställande resultat som att välja en ljusare bakgrund: vissa tydliga taggigheter visar sig, och beroende på tillfällig bakgrund.

— Alternativet — vilket jag har valt tills något bättre kommer fram — är att SPECIELLT för vit TrueTypeText skippa anspråken på DIREKT analog flytbild — vilket betyder att VitTexten INTE kan dupliceras, roteras, vändas, inverteras, kopieras med flytbildsverktygen. I P2 används därför (f.n.) bara en »rak grundtext».

— Vill man ha kopior av senaste VitTextTextIn, är det bara att ta om med T, Enter och Space.

— Man kan felaktigt tro att man NÅGOT skulle kunna KRINGGÅ VITTEXTSVÅRIGHETEN genom att välja en maximalt ljus textfärg typ RGB(254,255,255).

— Gör man det, alternativet överst, väljer man också ALGORITMENS minimalt separerande uttoningspixels förmåga att harmoniera med godtyckliga bakgrunder, och resultatet blir TAGGIGT: VitTexten kräver (liksom »svarttexten») en maximal uttoningsskala som kan matchas upp mot en godtycklig bakgrund, alternativet nederst ovan. Annars blir resultatet reducerad kvalitet.

— »Taggighetsfelet» (övre alternativet) blir mindre ju mörkare textfärg som används, medan den helt vita texten alltid ger max skärpa:

— Redan vid gråskalan 243 [textfärg RGB(243,243,243)], ovan, är taggighetsfelet i princip obefintligt. Samma text som ovan RGB(243,243,243) men mot svart bakgrund:

samt nedan till jämförelse mot tonad bakgrund:

   Vi är glada om det blir så snyggt.

   UPPENBARLIGEN finns någon mera avancerad algoritm i grunden. Men den är ännu här t.v. inte närmare känd. Tills dess får vi (i P2) finna oss i att VitTexten inte kan dupliceras på annat sätt än via upprepade T Enter.

— Programkoden är f.n. utformad för att (säkert) skydda mot avbrott typ AccessViolation i fallen VitTextTextIn — om man händelsevis råkar försöka med R(otera) V|H(vänd vertikalt|horisontellt): dessa operationer ger bara en tom textrektangel i fallet VitTextTextIn. Så: det ska vara helt riskfritt att använda|initiera alla kommandon.

 

TextIn — inledning

— Hur gör man för att också få med typen TrueType-teckensnitt i den samlingen?

 

 

— Alltså (vänsterbilden ovan): att kunna skriva in godtycklig TrueTypeText över godtycklig bakgrund och få den jämna fina teckensnittskonturen, utan fula taggigheter (högerbilden ovan)?

   ORDBEHANDLARNA (Word2000, OpenOffice) har den typen integrerad: lägger man in bilder som bakgrund under text, anpassas den överliggande texten (vänsterbilden ovan) så att den smälter in mjukt och »exakt» med bakgrunden.

CentralKodTextIn:

 

Om vi förstorar upp foten på ett TrueType-teckensnitt T (ovan här Times New Roman) och tittar efter, ser vi att »hela hemligheten» ligger i en mindre samlig UttoningsPixels i rundkanterna på en »rak» enfärgad TextKropp. KODEN i DELPHI4 för att räkna optimalt med »alla möjliga fall» — bilden ovan vänster i resultat — ser ut så här [TextIn Unit1T|2Okt2014][alla utom VitText, denna har en special; ... J:=255; I:=255-GrayS, sedan lika som nedan med aR=aG=aB=255]:

 

                ...

                J:= 255-GrayC;

                I:= GrayS-GrayC;

              if  (I>0)             and (I<=Round(J*1/10)) then g:= 1-0.05 else

              if  (I>Round(J*1/10)) and (I<=Round(J*2/10)) then g:= 1-0.10 else

              if  (I>Round(J*2/10)) and (I<=Round(J*3/10)) then g:= 1-0.20 else

              if  (I>Round(J*3/10)) and (I<=Round(J*4/10)) then g:= 1-0.30 else

              if  (I>Round(J*4/10)) and (I<=Round(J*5/10)) then g:= 1-0.40 else

              if  (I>Round(J*5/10)) and (I<=Round(J*6/10)) then g:= 1-0.50 else

              if  (I>Round(J*6/10)) and (I<=Round(J*7/10)) then g:= 1-0.60 else

              if  (I>Round(J*7/10)) and (I<=Round(J*8/10)) then g:= 1-0.70 else

              if  (I>Round(J*8/10)) and (I<=Round(J*9/10)) then g:= 1-0.80 else

              if  (I>Round(J*9/10))                        then g:= 1-0.90;

              {ORIGINALVERSIONEN|Project1| använde endast tre intervall. Efter flera mer

              eller mindre misslyckade försök att hitta alternativa ALGORITMER visade sig

              ovanstånde utmärkta resultat.}

              p:= 0.2;

{MED TONINGSIDENTITET|p| — uttoningspixlarna sammansmälter med bakgrundens pixlar:}

              Pc[4*x+2]:= Round( p*g*(Pa[4*x+2]) + (1-p)*g*aR + (1-g)*(Pb[4*x+2]) ) ;

              Pc[4*x+1]:= Round( p*g*(Pa[4*x+1]) + (1-p)*g*aG + (1-g)*(Pb[4*x+1]) ) ;

              Pc[4*x+0]:= Round( p*g*(Pa[4*x+0]) + (1-p)*g*aB + (1-g)*(Pb[4*x+0]) ) ;

 

I Programmeringsarbetet:

— Man behöver bara kolla upp gråtonsvärden för aktuella uttoningspixels (allt övrigt skippas), fastställa ett toningsintervall för dessa (här i 10 jämna steg), och sedan verkställa procentuella respektive RGB-andelar från Textdel(Pa) och Bakgrundsdel(Pb), samt tillfoga ett »TextFärgIdentitetsVärde» (p — här visuellt optimalt observerat resultat efter viss utprovning) som ger uttoningen mot bakgrunden textfärgens karaktär (annars framträder »fula rester»).

— Enkel ProgramÖvningsUppgift?

— Definitivt INTE. Grym utmaning om man inte vet något från början. Att brottas med dylika algoritmer — INNAN MAN HITTAR STILEN — kan HELT ta knäcken på en. För min egen del, flera gånger nära att bara ge upp (kasta ut datorn). Många DELEXEMPEL finns — mer eller mindre komplicerad matematik som man kan ställa upp till prövning — som ger JÄTTEFINA delresultat, som det ser ut. För att sedan, när man drar resultatet som helhet över en hel gråskala mellan vitt-svart förvandlas till rena mardrömmen. Dramatiken är, eller kan vara, milt sagt oerhörd — inte minst när lösningen seglar upp och sprider Ljuset. Ovanstående ger galanta resultat genomgående, samtliga fall.

 

 

 

RamToning:

 

Ramtoning

Antingen singulära bildavsnitt som kan tonas ut i ändarna, eller överUnder,

 

 

Tillämpningsområdena är ändlösa . . .

 

eller en förening av två olika bilder som kan tonas in i varandra — med olika (avgränsande) styrka:

 

FrameTone

Ctrl+F             Aktiverar|Avaktiverar RamToning (FrameTone)

Pilar             Upp|Ner|Höger|Vänster väljer uttoningsgräns

NumPad±                      väljer uttoningsstyrka

Space + NumPad±        väljer uttoningsgrad (uttoningsstyrkans förstärkning)

Ctrl+C                           kopierar resultatet till Urklipp

2BildsFörening             MoveCopyWhite : FlytKopia Övre över Undre, kopiera Ctrl+C, kör Ctrl+F, resultat Ctrl+C, avsluta Ctrl+F, resultat in Ctrl+V [förena Ctrl+Pilar]

 

 

 

 

 

Genom att kombinera olika lämpliga bilder kan (ytterst) finstämda (helt sagolika, normalt helt omöjliga) bildkompositioner framställas på det ytterst enkla sättet via FrameTone [»RamToning»].

   (Fotografen är MEDVETET ute i buskarna och LETAR efter »kombinationsobjekt». Sedan i hemmets lugna vrå utbryter rena jublet när arbetet sammanställs. Ytterst stimulerande verksamhet — och ibland litet krävande):

 

Foto:  20Aug2013  E25  Bild41 ·  3Jul2012  E12  Bild299  · Nikon D90 — Naturen

 

 

 

 

Vänligen ge rättelse:

 

— EUROPA 2014 — en nazistisk region som kallar sig och uppfattar sig DEMOKRATISK: ett rättsutövande system som garderat — friskrivit — sig MOT mänskliga rättigheter (ingen får tvingas tillhöra en sammanslutning) genom upphöjandet av tillhyggesinrättningar (friskrivningsklausuler) som existentiell bestämmande auktoritet, och därmed systematiska dödspsykningar mot och utdrivningar av våldsvägrare från samhällena — med följd i hejdlöst stegrat allmänt våld och respektlöshet: en totalt havererad rättsordning som driver omkring som ett sönderbrutet skepp i takt med att vattnet strömmar in och sänker skutan och naturvandaliseringen sprider sig som en löpeld genom mänskligheten: en återvändsgränd av fundamental övergripande existensförnekelse som påtvingas mänskligheten av, från och via samhällets bevarande propagandaorgan: all media utan undantag.

— Enda sättet att påvisa förödelsen: genom matematik och fysik, fullkomligt politiskt oberoende, självbärande relaterbar och minutiöst förklarbar naturlogik, att SÅ påvisa den Europeiska Intelligensens Grundläggande Misslyckande i Naturvetenskapen.

— Finns det ingen sådan »reserverad naturkraft» är det kört.

 

— NAZISMEN INFÖRDES MED OBLIGATORISK ALLMÄN FOLKLIG LYDNAD UNDER TILLGYGGESAUKTORITETER från mitten av 1800-talet.

— Efter andra världskriget förbjöds den preussiska staten av de allierade — men man behöll det centralt nazistiskt införda överhetssystemet med tillhyggesinrättningar som individmönstrande auktoritet: verksamheten från polis, åklagare och domare (från 1870 i hela Europa utom England) att påtvinga våldsvägrare våldsbegrepp, krigsman, för tillfället att få anklaga, misskreditera, driva ut, skymfa och skända den fredliga människans existensrätt och FÖRENINGSOBEROENDE mot tillhyggesinrättningar.

— Det och inget annat är grundvalen till våldets spridning, bristen på allmän trygghet, sundhet ordning och skick.

— In till den sekund då rättssystemet ställs till ansvar för sitt vedervärdiga uppträde, kommer icke en prick att ändras till det bättre i pågående allmänna samhällsutveckling: kunskapen är fridsamhetsgrundad, och konsekvensen att förakta den naturgrunden kan ingen kraft omintetgöra: våld föder våld, hat föder hat, och kärlek föder kärlek. Det är en evig lag.

 

 

 

Ursäkta (känsliga ombeds hoppa över följande):

— Jag förstår inte riktigt det här [Svar]:

— Naturkryddan bakom fotografierna från naturområdena som har inspirerat till de ytterst fina sammansättningarna som i exemplet ovan, verkar också vara allmänt föremål för följande statliga kommunala intressesfärer:

 

 

Från ca 2010:

— Kommunerna uppvisar verksamhet med omfattande, upprörande, naturingrepp — utan att någon som helst information lämnas till berörda närboende. Koll på webben för att hitta kopplingar resulterar i noll.

 

 

nersågning, borttagning av den naturliga sköna och lummiga växtligheten, efterlämnade spår av fulhet, vanvård, tydlig missaktning.

 

 

 

 

— Vi kommer garanterat aldrig att få något svar av de ansvariga för vandaliseringen, och som skulle medföra en förändring till det bättre. Så: Varifrån ska hjälpen komma? UtellMe.

— Överallt liknar allt, mer och mer, ett veritabelt kalhygge. Noll naturkunskap. Max EgenMaktsProfiteringsBehov.

 

 

·         Människor som sågar ner Granen/Tallen DÄRFÖR ATT DEN BARRAR JU.

·         Människor som sågar ned Björken DÄRFÖR ATT DEN LÖVAR JU.

 

— Vad är det? Uppenbarligen INTE naturkärlek:

 

·         Vi ÄLSKAR träden DÄRFÖR att de ÄR träd MED Barr och Löv.

 

EGENkroppsHAT? NaturÄndamålsFörakt?

   Sanningshat? Generellt?

— Högljuddhet, högmodighet, världsvanhet, noll bekymmer — stark upprördhet när Sanningen visar sig.

 

 

— Men det kan ju gömma sig nån bakom!

— Det är uppenbarligen inget naturproblem utan ett samhällsproblem.

— Om det finns människor som verkligen tror att man löser samhällsproblem genom att börja ge sig på naturen, eller som ens tror att ett naturingrepp skulle kunna sammanhänga med någon resultatbild i samhällsproblemets lösning — kolla historien: visa exempel — är det tydligt att de människorna i så fall har tagit sig vatten över huvudet: naturvandalisering. Våldets slutliga eskalering. Naturföraktets slutliga ansikte. Problemgrundens slutliga avtäckande: problemet ligger i samhällets rättsutövande värderingar som har grundlagt våld och oskick.

 

— Jag skulle vilja gå så långt som till hit:

— OM det finns någon ENDA människa på Jorden 2014 som anser ATT lösningen av samhällsproblem kan gynnas av naturingrepp, på något som helst enda sätt och vis, var i så fall vänlig att berätta för mig, om ingen annan, VARIFRÅN den uppfattningen kommer och vad den grundas på. Ge ett exempel. Jag vill mena det: finns inget sådant exempel. Men visa gärna.

 

 

— Varför då?

— Blommor i StadsCentrum? Står dessa också i tur att sågas? Är det läge snart att också uppvisa och stoltsera med samma nerskräpningsNit där som i den övriga milsvida NaturParksHanteringen?

   Jag tycker mig se en Strömning som verkar ha satt sig i sinnet att KNÄCKA Naturen, förstöra och utarma så mycket som möjligt genom att HÄVDA SIG SJÄLV ÖVERLÄGSEN, att försöka sätta något Nytt i Naturens urgamla ställe, och också tro sig om att vara mäktig att kunna genomföra det Programmet. Det är det verkligt intressanta. DNA-genierna, Herrefolket, är tydligen på frammarsch.

   Det är definitivt något som inte är som det ska — sedan runt 2010 enligt observationer.

 

Det finns ingenting kvar av ovanstående nu (2014).

— Bara för 4 år sedan fanns typen ovan i stort sett att SE kring alla möjliga närliggande farleder — hela sommarhalvåret.

— Säg den plats i närområdena man nu idag 2014 hittar något liknande. Finns inte.

— Kommunerna|Staten röjer ner och förstör och tar bort allt som en gång fanns kring i stort sett alla farleder — 10 meter ut på alla vägsidor: stympar, sliter sönder, lämnar efter sig intryck av stark vanvård och vanskötsel: Det ser ut som en KRAFT som försöker etablera begreppet KALKYGGE — statlig skogsvård — som något acceptabelt — dvs., i klartext: skogsbrandsupprinningsområden i stor mängd etableras löpande: öppna platser i stor mängd med mängder av död växtlighet: torrt och varmt på ytan, kvavt, hett och fuktigt inunder, perfekt för kemisk självantändning, eller bara perfekt bränsle om en eld uppkommer.

   Ovanstående enskilda sommarvyer, en gång i stor mängd på många platser i närområden, i sig urfina, finns inte längre (2014). Runt vägar och farleder, vattendrag och övrigt, drar en Statlig Kraft omkring med avverkningsmaskiner och sänker naturvärdena konstant, kontinuerligt. Det verkligt intressanta med den verksamheten är att vi redan VET att den INTE kommer att bli framgångsrik i Natursamvaron. Människan är inte skapt så. Så, i takt med att Vettlösheten sprider sig, visar sig konsekvenserna.

 

Svar, se även AntecknatNatur

 

Foto:   27Aug2014  E18  Bild146

 

InverteraKontrast30 ¦ normal:TonaUpp70 ¦ Kontrast 30 — Skies. PerfectAssembly. Project1 DELPHI4Test2011+.

Svar — till prövning

FrågaNaturen

 

Förståndslösheten manifesterad.

— Det finns garanterat ingen som helst rationell, logisk, förståndsgrund på vars fundament någon alls DIALOG med den ansvariga beslutsfattande instansen kan iordningställas.

— HUR kan jag påstå det?

— Har du sett några Poliser som är ute och jagar Gärningsmännen?

   Nej. Polisen, hela rättssystemet, ingår i — ÄR — besättningen.

— Har du sett eller läst någon Tidningsartikel som berättar om förödelsen?

   Nej. Journalistkårerna är en del av verksamheten.

— Har du över huvud taget hört talas om eller sett något MEDIA alls som ens omnämner de omfattande, tydligt vanställda, naturingreppen? Jag ser ingen. Verksamheten bara fortsätter, utvidgas.

   Vad visar sammanhanget?

   Alldeles tydligt: En med anspråk ERÖVRANDE KRAFT är på väg IN i Naturen för att uppenbarligen försöka agera Existentiell Myndighet: »VäxtGUDEN».

   DET var det intressanta.

— Och varför skulle DET vara det intressanta?

— Därför att ALLA VET REDAN att när det kommer till NATURKUNSKAPERNA på Planeten Jorden året 2014, är det enda som finns från Statligt och Kommunalt håll det som är grundat på det här: militär exercis och plågsamma djurförsök under 150 år — tillsammans med systematiska dödspsykningar mot våldsvägrare: polis, åklagare, domare: allmänhet. Inget annat.

   Vanföreställningar om Natur, Moral och Etik tävlar.

   Med andra ord, och förutsatt välgrundat:

— Det finns ingen RATIONELL argumentgrund. Handlingen grundas alldeles avgjort tydligt på erövringsprinciper — noll information till den berörda allmänheten — en föreställning som grundas på Överhet, Myndighet med Vapenmakten — yxa — som enda historisk referensgrund.

— Vi använder TIDEN bättre genom att åka ut till vägkanten, sätta oss ner och börja Prata med de avslitna Ungstammarna. Naturligt Engagemang.

 

DEN ANSVARIGA BESLUTSINSTANSEN (Kalle och Stina på HuvudKontoret) TROR helt säkert, att EFFEKTEN av avslitningarna, stympningarna och förödelsen ska FRÄMJA EN MINSKNING I DEN ALLMÄNT ÖKANDE RESPEKTLÖSHETEN — kamouflerad av »allmän trafiksäkerhet» med NOLL natursamverkan (»naturliga flyktvägar»).

— Det är, således, hög tid för Kalle och Stina på Huvudkontoret att börja leta efter de borttappade glasögonen som man inte hittar, genom att känna efter på näsan: de sitter redan på.

 

Inte förrän de fredliga människornas rätt ställs fram, den som man våldfört sig på under 150 år och som bär ansvaret för våldets utbredning, hela Europa, hela Världen, kommer en ändring.

 

KONSEKVENSERNA AV VETTLÖSHETER har aldrig försökt smita ifrån vardagen. Vår tids Speciella Övningar innebär inget undantag.

 

Hej.

 

Foto:   27Aug2014  E18  Bild147

 

InverteraKontrast30 ¦ normal:TonaUpp70 ¦ Kontrast 30. PerfectAssembly. Project1 DELPHI4Test2011+.

 

 

Är det här den nya modellen för planteringar i Stadskärnorna?

— Därför att OM man inte hyser större respekt för Naturskönheten på Övriga Domäner, vadan den Speciella Vurmen?

   För den som inte riktigt förstår andemeningen bakom finns en snabbare kortform: FYA.

 

Vi — människan — kan inte framgångsrikt börja favorisera vissa naturområden framför andra, eftersom alla naturområden är likaberättigade (höger framben har inget företräde för vänster, osv.). Med ovanstående förnämligt exemplifierade flora av kommunala och statliga företagsamheter, blir effekten följaktligen denna [OBS, GÄLLER INTE DE SOM SPENDERAR TIDEN I NATUREN BAKOM BILDÖRRARNA DÄR FÖGA AV OVANSTÅEN DE SYNS]: upprördhet, pressande stress, upplevd sänkt trivsel, associerad vanmakt. Det finns bara en Kraft som gynnas av den typen: våld: ohälsa.

 

 

 

CommanderDoit, RitaVerktyg

26Okt2014

 

 

Unit1CD ¦ Ctrl+Shift+C

 

  Procedure TForm1Edit6Change;

  Procedure ComPan;

  Procedure Commander(var Key: Word; Shift: TShiftState; Code: Integer = 0);

 

Integrerade rutiner på Im1mouseMove.

 

KeyDown|KeyPreview

VK_INSERT

VK_ESCAPE

Delad resurs för Palett(F4), Flytbild(Ctrl+Pilar) och Markörflyttning(Pilar)

Image1MouseMove

Edit6KeyUp|Dn

Edit6Change                                                                                

 

Särskilda variabler (omskrivna från utvecklingsprogrammet T2014):

 

Status[12] = C = CommanderDoit: Bool;

Status[13] = 1 = PenLasso: Bool;

Status[14] = 1 = LineConnected: Bool;

Status[15] = 0-7 = ComDoTool: Char;

Status[18] = 1 = SetColorCD ¦ Pen | Line  | SelectColor | : Bool;

 

Special på Unit1FormKeyDown för att hindra InsertFlag vid färgval:

 

      VK_INSERT,VK_DELETE:begin {CurFlag:}

                  if CommanderDoit then exit;

 

Special också på Unit1 MouseUp för PenLasso.:

 

 

(Trixiga)Ändringar T2014 Unit5 CommanderDoit|PenLasso:

     if (Pos('CRL',S)=1)or(Pos('EPS',S)=1)then

     begin

       {ONLY Status15=|5|7¦(Se KEYS):}

       if S[Length(S)] in ['C','F'] then

       begin

OK 29Okt2014.

 

Unit1 KeyDown:

 {MoveCOPY|AND|10Sep2014:}

      Ord('C'): begin

                  if CommanderDoit then exit;

 

 

 

 

Till vilken nytta?

 

När vi nu (9Sep2014) har hunnit så här långt — flytbildsfunktionen insatt i elementärt bildhanteringsprogram — kan vi fråga oss:

— Vilka verktyg bör NU ett sådan ELEMENTÄRT datorstött bildhanteringsprogram ha för att vara till verklig NYTTA i det allmänna arbetet med bilder?

   Jättekul fråga.

   Säg nämligen den funktion i bildämnet man INTE vill ha med. Snälla.

— Vi vill ha ALLT. Enkelt. Snabbt.

 

Vad skulle till exempel P2-programmet som det nu ser ut kunna användas till?

— Först och främst som en mellanVERKSTÄLLANDE BILDSTORLEKSMASK:

— RamBildsMask:

 

Tillämpning, [F5]

   

 

— Man vill ha en viss (liten) bildstorlek, för att kunna sätt lika stora bilder i rader och kolumner:

— PERFEKT läge är det då att ha en P2-hjälp MED EXAKTA FLYTBILDSEGENSKAPER:

— Man kan precis och exakt ta ut det avsnitt man vill se, och sedan bara kopiera den bildrutan med Ctrl+I: endast bildrutans del kopieras till urklipp.

— Sedan kan ett annat öppet P2 ta in den preparerade bildkopian och snyggt och prydligt — på bestämda exakta flytbildssteg — och bekvämt (med förutbestämda intervall) ordna samlingen i rader och kolumner.

— SIST kan HELA den sammanställningen exporteras via Ctrl+I till t.ex. Paint (jag gör det ALLTID — arbetsrytmen är: sammanställ i typ P2, exportera till Paint via urklipp med Ctrl+I, Ctrl+V; spara dessa upprepat nya exporterade ändringar i Paint på samma plats med Ctrl+S: enkelt, säkert, garanterat viss distans mellan kopieringar som gör det svårt att fibbla bort original: missar man något, finns alltid MINST ett sparat tidigare original kvar), och därifrån sparas på lämpligt format (PNG, för att bevara alla RGB-färgerna, om det är önskemålet).

 

JÄMFÖR TILL EXEMPEL FLYTBILDSVERKTYGEN I PAINT:

Rena mardrömmen. Min mening.

— Det GÅR i Paint att flytta ett intaget objekt med pilar — men bara ett pixelsteg i taget:

— Vi får hålla på tills nästa julafton innan något blir gjort.

— Man kan VISST klicka på intaget och FLYTTA MED MUSKNAPPEN NEDTRYCKT, och KOMBINERA med »slutlig precisionspixelposition» i enstaka pixelsteg — men med den förträffliga bekväma arbetssegern att då tvingas lämna tangentbordet med de redan parkerade superinstrumenten VänsterFingrar vid Ctrl och HögerFingrar vid Piltangenterna och NummerBordet.

— I P2-programmet ovan finns ingen musbaserad bildflyttning, inte alls över huvud taget.

— NÄR jag kommer över rit- och bildprogram som HAR sådana funktioner — flytta bild med mus — reagerar jag alltid på samma sätt: gud så TRÄAKTIGT, KLUMPIGT, LÅNGSAMT: omständligt. Rena fängelset.

— Jag vet inte riktigt varför. Jo. Kanske: Tangentbordet är SNABBT ÅTKOMLIGT, speciellt nämnda tangentgrupper vänster-höger hand: man kan hela tiden HÅLLA EN tankeTRÅDobruten I ARBETET utan att behöva tänka på att »lämna området och börja LETA efter muskroppen vid sidan om». Det är KONTINUITETEN. FLYTET. Glädjen att INTE TVINGAS BLI AVBRUTEN. Att få använda de enklaste av alla medel, betyder att DESTO MERA UTRYMME GES FÖR FOKUS PÅ ANNAT. Timme in, timme ut.

— Men jag kanske överdriver.

— I DELPHI4 har vi hur som helst möjligheter att testa hur våra egna önskemål fungerar i praktiken.

 

 

Elementär flytbildsteknik — grundexempel i DELPHI4

 

 

 

 

 

EditColorsUnit1C, ecU1C

 

 

EditColors

Kodblocken med variabler till procedurerna i Unit1C|P2|18Sep2014

Hela Unit1C¦P2|19Sep2014

 

unit Unit1C;

{Unit1C — EditColorsUnit|17Sep2014}

interface

uses

Windows, Messages, SysUtils, WinTypes, WinProcs,

Classes, Graphics, Forms, Dialogs, StdCtrls,

FileCtrl,ExtCtrls, Controls, ShellAPI,

Math, Clipbrd, ComCtrls;

{GlobalVARIABLES|Constants .......................................:}

type

  TecTimer = class(TTimer)

  Procedure OnEditColors(Sender: TObject);

  end;

 

var

  ecTimerON:   Bool;      {Status37=1=On|0=off}

  ecTimer:     TecTimer;  {TypeDeclaration som ovan|ecTimer.Create|Free Unit1FormCreate}

  ecPanON:     Bool;     

  eCol:        TColor;    {HandlingColor|FB}

  fgC21,bgC21: TColor;    {TransferColors}

  FBflag:      Char;      {ForegroundBackgroundColorFlag}

  S:           string;    {Används på Alt+NumPad 0..9}

  KeyNP09:     Bool;      {Status38=1 if anyNP|0-9}

{GlobalVARIABLES|Constants ........................................}

{GlobalPROCEDURES & Functions - GlobalDeclarations ...............:}

 

  Procedure  vRGBtoHSB(var C1,C2,C3: Integer);

  Procedure  vHSBtoRGB(var C1,C2,C3: Integer);

  Procedure EditColors(var Key: Word; Shift: TShiftState);

 

{GlobalPROCEDURES & Functions - GlobalDeclarations ................}

 

implementation

uses

Unit1;

{MOTSVARANDE "uses Unit1C" måste tillfogas på Unit1 antingen

1. i |uses| direkt efter |interface| LÄNGST UPP - om detaljer som står

explicit under Unit1:s Interface används, eller

2. som närmast ovan i Unit1-makens Implementation|Uses.

- Se dessa detaljer utförligt i DELPHI4help,

Circular unit references: regeln är att Unit:s inte får referera

varandra i samma uses-block|Delphi vägrar kompilera då.}

{LocalVARIABLES|Constants ........................................:}

var

  C7:        Integer;

  RHR:       array [1..2] of array [1..3] of Char;

  vRGB,vHSB: array [1..3] of Integer;

  rRH,sRH:   Integer;

  kC,ecStep: Integer;

  ecT:       TPoint;

  ColFG:     TColor;

{LocalVARIABLES|Constants .........................................}

{ActualPROCEDURES & Functions - - - - - - - - - - - - - - - - - - :}

 

{StartIDLE(100mS)|EditColorsPan12|SHOOTleftMB(10mS)|Stop|CloseEditColors:}

{Procedure TForm1ecTimerTimer(Sender: TObject)|Unit5|T2014|ecTimer|Unit1:}

Procedure TecTimer.OnEditColors(Sender: TObject);

var

  W: Word;

begin with Form1 do begin

  if not Panel12.Visible then exit;

  if GetKeyState(VK_LBUTTON)<=-127 then

  begin

    ecTimer.Interval:= 10;

    W:= Ord(#2);

    EditColors(W,[]);

    exit;

  end

  else

  begin

{STANDby:}

    ecTimerON:=False;

    ecTimer.Interval:= 100;

{RENSA Alt+NumPad0..9 Input om Ångra före 3 inslag:}

    if (GetKeyState(VK_MENU)>-127)

    and(Length(S)<3)

    and(KeyNP09)

    then

    begin

      S:= '';

      KeyNP09:=False;

      Label1.Caption:= 'Clear';

    end;{endIfÅngraInslagFöre3}

  end;{endEcTimerStandBy}

end;{endWithForm1}

end;{endTForm1ecTimerTimer|14Jul2014 Uni5 T2014|17Sep2014|Uni1C|P2}

{ANVÄNDS till RGB|HSB|ScrollRows istf.MouseMove.}

 

{Från RGB till HSB|Formelsamligar finns i bl.a. Wikipedia|2014:}

Procedure vRGBtoHSB(var C1,C2,C3: Integer);

var

    R,G,B:       Byte;

    H,S,L:       Integer;

  rH,rL,D:       Real;

  MinRGB,MaxRGB: Real;

begin

              R:= C1;

              G:= C2;

              B:= C3;

{HUE|H:}

              rH:= arctan2(sqrt(3)*(G-B),2*R-G-B)*180/pi;

              if rH<0 then rH:= 360 + rH;

              H:= Round(255*rH/360);

{BRIGHTNESS|L:}

              MinRGB:= MinValue([R,G,B])/255;

              MaxRGB:= MaxValue([R,G,B])/255;

              rL:= (MaxRGB + MinRGB)/2;

              L:= Round(255*rL);

{SATURATION|S:}

              D:= (MaxRGB - MinRGB);

              {if (R+G+B)>=765 then S:= 255 else|VITTingenFärgMättnad:S=0=Vitt|Svart:}

              if D=0 then S:=0 else

              S:= Round(255*(D/(1 - Abs(2*rL - 1))));

              if S>255 then S:= 255;

              C1:= H;

              C2:= S;

              C3:= L;

end;{endValueRGBtoHSB}

{WIKIPEDIA m.fl. webben ger uppslag. Ovanstående utvecklat efter dessa, samt testat

med olika testalgoritmer och jämförelser. Notera att speciellt HUE-parametern ALLTID

kommer att ge vissa förluster beroende på dess utomordentliga omfattning. Enligt delvis

systematiska test (Juli2014) är maximala avvikelsen i RGB-enheter HÄR max 8 — mycket

sällsynt, medan 4, 3 och 1 är vanligare men fortfarande bara syns sporadiskt i grovtest:

— Testprogrammet: räkna tillbaka till RGB från HSB och läs av differensen:}

{Från HSB till RGB:}

 

Vi har hela tiden koll på RGB och HSB i det färdiga programmet via EditColorsPanelen (NumPad 5).

 

 

P2-dumpen ovan 19Sep2014 efter en viss omstuvning av komponenterna och tillägg av en övre extra Statuspanel — enbart en i botten blir i snålaste laget.

— Senast valda färg (B bakgrund, N förgrund ¦ visas övre statuspanelen) kommer upp för Redigering med NumPad 5; efter redigering kan den nya färgen väljas med Enter (eller O) eller Ångra med Esc (eller C), eller ta om från början med Reset.

— Varje ändring i någon av R G B H S B återspeglas omedelbart i alla övriga. Full SpektralKoll.

 

Procedure vHSBtoRGB(var C1,C2,C3: Integer);

var

  Col:       TColor;

  I,K,D,M,X: Real;

  H,S,L,J,A: Integer;

  bD,bX,b0:  Byte;

begin

{HSBtoRGB;}

              H:= C1;

              S:= C2;

              L:= C3;

 

              Col:= 0;

              I:= 6*H/255;

              //I:= 6*(H+0.001)/255;

              {Originalet|I:= 6*H/255|+0.001¦annars RGB=0 vid H=0=clRed|5.9=any<6|:}

                if I>=6 then I:=5.9;

              {|=6|missar H=255 som då ger RGB=0 vid H=255|>=6|löser saken|13Jul2014.}

              J:= Floor(I);

              D:= (1 - Abs(2*L/255 - 1))*S/255;

              A:= Round(H/255*360);

              K:= Floor(A/60) mod 2 + A/60 - Floor(A/60);

              X:= D*(1 - Abs(K - 1));

              M:= (L/255 - D/2);

 

                bD:= Round(255*(D+M));

                bX:= Round(255*(X+M));

                b0:= Round(255*(0+M));

 

              {if H=0 then Col:=RGB(b0,b0,b0) else|UtgårMedOvanstående|+0.001|if.}

              {Med|I=6H/255|J=Floor(I)|blir|J=0|med|H=0|: ovanstående »UtvecklingsRest».}

              begin

                case J of

                   0: Col:= RGB(bD,bX,b0);

                   1: Col:= RGB(bX,bD,b0);

                   2: Col:= RGB(b0,bD,bX);

                   3: Col:= RGB(b0,bX,bD);

                   4: Col:= RGB(bX,b0,bD);

                   5: Col:= RGB(bD,b0,bX);

                end;

              end;

 

              C1:= GetRValue(Col);

              C2:= GetGValue(Col);

              C3:= GetBValue(Col);

end;{endValueHSBtoRGB|12Jul2014.}

 

{AllKeys|Shift|12Jul2014|ExecuteColor=Colr:}

{:Alla Nästade Procedurer:

Procedure EditColors(var Key: Word; Shift: TShiftState)

  Procedure Pan60SetUp(Colr: TColor; N: Integer = 0)

  Procedure SwitchSide(A: Integer)

  Procedure SelRow(I,A: Integer)

  Procedure SetRow(A: Integer; N: Integer = 0)

  Procedure CheckEcTimer

:}

Procedure EditColors(var Key: Word; Shift: TShiftState);

var

         Col: TColor;

  A,A1,A2,A3: Integer;

  Procedure ParIN;

  begin

            RHR[1][1]:= 'R';

            RHR[1][2]:= 'G';

            RHR[1][3]:= 'B';

            RHR[2][1]:= 'H';

            RHR[2][2]:= 'S';

            RHR[2][3]:= 'B';

             kC:= 0;

            rRH:= 1;

            sRH:= 1;

     {kC=0|RGBside: kC=1|HSBside: rRH|123|Rows.}

     {kC alterneras med Caps: rRH med UpDn.}

  end;

 {INITIALIZE EditColorsPanel:}

  Procedure Pan60SetUp(Colr: TColor; N: Integer = 0);

  var

     B: TBitMap;

     S:  string;

     tR,tB: TRect;

     C,I: Integer;

     label  EditNew;

  begin with Form1 do begin

  if Abs(N)=1 then goto EditNew;

 

     with Panel12 do begin

       Width := 557;

       Height:= 138;

       if Width+10 > Form1.Width then Form1.Width:= Width+10+50;

       Top:= Form1.Height - Height - Panel2.Height - 23;

 

       if C7=0 then begin

              Left:= Form1.Width - Width -10;

              Anchors:= [akRight,akBottom];

                    end;

       if C7=1 then begin

              Left  := 20;

              Anchors:= [akLeft,akBottom];

                    end;

       BringToFront;

       Show;

     end;{endWithPan12}

                 S:= '';

                 fgC21:= fgCol;

                 bgC21:= bgCol;

                 if not (FBflag in ['B','N']) then

                 FBflag:= 'N';

     {SELECT EDITING COLOR:}

                 if FBflag='N' then Colr:= fgC21 else Colr:= bgC21;

                 ColFG:= Colr;

     with Image5.Canvas do begin

       Brush.Color:= clWhite;

       FillRect(ClientRect);

     end;{endWithIm5Canvas}

{=======}

 EditNew:

{=======}

       S:= ExtractFilePath(Application.ExeName) + 'EC21.bmp';

       if FileExists(S) then

       begin

     {Im5¦AutoSize=False|AlClient|Visible:}

          Image5.Picture.LoadFromFile(S);

     {SHOW COLOR|Colr=RedigeringsFärgRektangeln på Im5|fg|bgCol|senaste:}

          tR:= Rect(256,45,299,100);

          with Image5.Canvas do begin

               Brush.Color:= Colr;

               eCol:= Colr;

     {Colr medsänds här i denna Procedure Pan60SetUp(Colr: TColor; N: Integer = 0):

      — Den används också vid den upprepade redigeringen: Image5 läses in upprepat.

      — eCol är slutfärgen som ska överföras, om alls.}

     {EditedACTUALforUse:}

               FillRect(tR);

               B:= TBitMap.Create;

                 try

     {SET|RGB|BarOffset=19;42|yStep=20:}

               C:= 0;

            for I:= 1 to 3 do

            begin

                 case I of

                   1: begin C:= GetRValue(Colr); A1:= C; vRGB[1]:=A1; end;

                   2: begin C:= GetGValue(Colr); A2:= C; vRGB[2]:=A2; end;

                   3: begin C:= GetBValue(Colr); A3:= C; vRGB[3]:=A3; end;

                 end;{endCase}

               tB:= Bounds(147,42 + (I-1)*20,73,19);

               tR:= BitMapRect(tB,B);

               with B.Canvas do begin

                 Font.Name:= 'Microsoft Sans Serif';

                 Font.Size:= 7;

                 Font.Style:= [fsBold];

                 Font.Color:= 0;

                 Brush.Color:= clWhite;

                 FillRect(tR);

     {R|G|B|Value:}

                 B.Transparent:= True;

                 B.TransparentColor:= clWhite;

                 TextOut(0,0,IntToStr(C));

                 Image5.Canvas.Draw(227,45 + (I-1)*20,B);

                 {OBS|FillRectFÖRST — med TYP TransparentColor. AnnarsIngenFunktion.}

               end;{endWithB}

     {R|G|B|Slide|Set:}

               {CopyMode:= cmSrcAnd;

               CopyRect(Bounds(227,45,tR.Right,tR.Bottom),B.Canvas,tR);

               {SammaNetto|SomDrawViaTransparent.}

               C:= C div 2 + 19;

               B.Transparent:= False;

               B.Canvas.CopyRect(tR,Image5.Canvas,tB);

               Brush.Color:= clWhite;

               OffsetRect(tR,C,0);

               FillRect(tB);

               Draw(C,42 + (I-1)*20,B);

            end;{endFor}

     {endSET|RGB| ......................}

     {SET|HSB|BarOffset=336;42|yStep=20:}

     {HSBtoRGBmode:}

          if kC=1 then begin

              A1:= vHSB[1];

              A2:= vHSB[2];

              A3:= vHSB[3];

          end

          else

     {RGBtoHSBmode:}

          begin

              vRGBtoHSB(A1,A2,A3);

              vHSB[1]:= A1;

              vHSB[2]:= A2;

              vHSB[3]:= A3;

          end;

     {value|side|row| RGB|HSB.}

            for I:= 1 to 3 do

            begin

                 case I of

                   1: C:= A1;

                   2: C:= A2;

                   3: C:= A3;

                 end;{endCase}

     {R|G|B|Slide|Value:}

               tB:= Bounds(464,42 + (I-1)*20,73,19);

               tR:= BitMapRect(tB,B);

               with B.Canvas do begin

                 Font.Name:= 'Microsoft Sans Serif';

                 Font.Size:= 7;

                 Font.Style:= [fsBold];

                 Font.Color:= 0;

                 Brush.Color:= clWhite;

                 FillRect(tR);

                 B.Transparent:= True;

                 B.TransparentColor:= clWhite;

                 TextOut(0,0,IntToStr(C));

                 Image5.Canvas.Draw(311,45 + (I-1)*20,B);

                 {OBS|FillRectFÖRST — med TYP TransparentColor. AnnarsIngenFunktion.}

               end;{endWithB}

     {H|S|B|Value:}

               C:= C div 2 + 336;

               B.Transparent:= False;

               B.Canvas.CopyRect(tR,Image5.Canvas,tB);

               Brush.Color:= clWhite;

               OffsetRect(tR,C,0);

               FillRect(tB);

               Draw(C,42 + (I-1)*20,B);

            end;{endFor}

 

                 finally

               B.Free;

                 end;

      {RGB|HSB|vertACTIVELabel:}

            Font.Name:= 'Times New Roman';

            Font.Size:= 9;

            Font.Style:= [fsBold];

            Font.Color:= clWhite;

            Brush.Color:= RGB(0,127,255);

            TextOut(4 + kC*534,44 + (rRH-1)*20,' '+ RHR[kC+1][rRH] +' ');

            {Start¦kC=0|rRH=1.}

          end;{endWithIm22Canvas}

       end;{endIfFileExists}

  end;{endWithForm1}

  end;{endPan60SetUp}

  Procedure SwitchSide(A: Integer);

  begin with Form1.Image5.Canvas do

   begin

              Col:= RGB(0,127,255);

              Font.Name:= 'Times New Roman';

              Font.Size:= 9;

              Font.Style:= [fsBold];

    {A=0=RGBside|A=1=HSBside ¦ A=0: RGBsideToHSBside ¦ A=1: HSBsideToRGBside:}

    {RestorePrevious:}

              Font.Color:= 0;

              Brush.Color:= clWhite;

              TextOut(  4 + A*534,44 + (rRH-1)*20,' '+ RHR[A+1][rRH] +' ');

    {DrawNew:}

              Font.Color:= clWhite;

              Brush.Color:= Col;

              TextOut(538 - A*534,44 + (rRH-1)*20,' '+ RHR[A+1][rRH] +' ');

              sRH:= A+1;

   end;{endWithForm1Im22}

  end;{SwitchSide|13Jul2014.}

  Procedure SelRow(I,A: Integer);

  begin with Form1.Image5.Canvas do

   begin

    {I=-1UP|+1DOWN ¦ A=kC = 0=RGBside|1=HSBside:}

              Col:= RGB(0,127,255);

              Font.Name:= 'Times New Roman';

              Font.Size:= 9;

              Font.Style:= [fsBold];

              Font.Color:= 0;

              Brush.Color:= clWhite;

    {CLEAR:}

              TextOut(4 + A*534,44 + (rRH-1)*20,' '+ RHR[A+1][rRH] +' ');

     rRH:= rRH + I;

     if rRH=4 then rRH:=1;

     if rRH=0 then rRH:=3;

    {RGB|HSB|vertACTIVELabel:}

              Font.Color:= clWhite;

              Brush.Color:= Col;

    {SHOWSelected:}

              TextOut(4 + A*534,44 + (rRH-1)*20,' '+ RHR[A+1][rRH] +' ');

   end;{endWithForm1Im22}

  end;{endSelRow}

  {SetRow(0,N>0) för nytt RGB|HSB-värde:}

  Procedure SetRow(A: Integer; N: Integer = 0);

  begin

           Col:= Form1.Image5.Canvas.Pixels[256,46];

         if kC=0 then begin

           if (A=0)and(N>0) then vRGB[rRH]:= N;

      {EDIT:}

           vRGB[rRH]:= vRGB[rRH] + A*ecStep;

      {SafeLimits:}

           if vRGB[rRH]>=256 then vRGB[rRH]:=255;

           if vRGB[rRH]<= -1 then vRGB[rRH]:=0;

      {SHOWresult:}

           Col:= RGB(vRGB[1],vRGB[2],vRGB[3]);

           Pan60SetUp(Col,-1);

           exit;

         end;{endIfkC=0}

 

         if kC=1 then begin

           if (A=0)and(N>0) then vHSB[rRH]:= N;

      {EDIT:}

           vHSB[rRH]:= vHSB[rRH] + A*ecStep;

      {SafeLimits:}

           if vHSB[rRH]>=256 then vHSB[rRH]:=255;

           if vHSB[rRH]<= -1 then vHSB[rRH]:=0;

      {Transfer:}

          A1:= vHSB[1];

          A2:= vHSB[2];

          A3:= vHSB[3];

          vHSBtoRGB(A1,A2,A3);

          vRGB[1]:= A1;

          vRGB[2]:= A2;

          vRGB[3]:= A3;

      {SHOWresult:}

           Col:= RGB(vRGB[1],vRGB[2],vRGB[3]);

           Pan60SetUp(Col,-1);

           exit;

         end;{endIfkC=1}

  end;{endSetRow}

  Procedure CheckEcTimer;

  var

    D,T: TPoint;

    I,J,I1,J1: Integer;

    tB: TRect;

  begin

    if ecTimerON=False then

    begin

      ecTimerON:=True;

      GetCursorPos(ecT);

      exit;

    end;

    GetCursorPos(T);

 {EXECUTE MOUSE MOVE|FindSlides:}

    //Form1.Label1.Caption:= IntToStr(T.X - ecT.X);

  {FindFocusRect|:}

  {tB:= Bounds(RGB|019¦147,42 + (I-1)*20,73,19):

   tB:= Bounds(HSB|336¦464,42 + (I-1)*20,73,19): 336=317+19:

   SlidPanelerna befinner sig|I=|1|2|3|:

   tB:= Bounds(RGB¦vRGB[I] div 2 +  19,42 + (I-1)*20,73,19):

   tB:= Bounds(HSB¦vHSB[I] div 2 + 336,42 + (I-1)*20,73,19):

   Ovan skissen till det färdiga:}

    I1:=0; J1:=0;

    D:= Form1.Image5.ScreenToClient(T);

    for I:= 1 to 2 do

    begin

      for J:= 1 to 3 do

      begin

        if I=1 then

        tB:= Bounds(vRGB[J] div 2 +  19,42 + (J-1)*20,73,19) else

        tB:= Bounds(vHSB[J] div 2 + 336,42 + (J-1)*20,73,19);

        if PtInRect(tB,D) then begin

         I1:= I; J1:= J;

         Break;

         exit;

        end;

      end;

    end;

 {EXECUTE MOUSE MOVE|DrawSlides|RGBtoHSBtoRGB:}

    if ecTimerON then

    begin

    kC:= I1-1;

    rRH:= J1;

    I:= (T.X - ecT.X)*2;

      J:= ecStep;

      ecStep:=2;

    SetRow(I);

    ecTimerON:=False;

      ecStep:=J;

    end;

    Form1.Label1.Caption:= IntToStr(T.X - ecT.X) + ' |: ' +

    IntToStr(I1) +';'+ IntToStr(J1);

  end;{endCheckEcTimer|StartUnit1|LButton}

label Final;

begin with Form1 do begin {Procedure EditColors|Panel12|Im22:}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

{HitFrån|ecTimer|Via|MouseLeft|EditColorsPan|ON:}

{Säkra FormKeyDownHIT ·························:}

               SExit:= True;

{Säkra FormKeyDownHIT ·························.}

{#2 från ecTimer:}

               if(Key=Ord(#2))then

               begin

                 CheckEcTimer;

                 exit;

               end;

{INITIALIZE|EditColors|Panel12|#1FrånZoomPlus|KeyADD:}

               if(Shift=[])and(Key=VK_NUMPAD5) then

               begin

                 if ecPanON then goto Final;

{SpecialModuleIDENTIFIER|ToUnit1 KeyDown:}

                 ecPanON:= True;

                 Key:= Ord(#1);

{LADDAR PARAMETRAR:}

                 ParIN;

{VISA|Panel10=fgCol¦Panel9=bgCol:}

                 if FBflag='N' then

                 Pan60SetUp(fgC21) else

                 Pan60SetUp(bgC21);

         {FBflag=N för Förgrund, B för Bakgrund, sätts via Tangent N|B|Unit1.}

{STEGLÄNGD|Starta »MouseMoveTimer»:}

                 ecStep:=5;

                 ecTimer.Enabled:= True;

                 S:= '';

{Unit1|Distrib.Nav|Reserverar alla KeyDownHit:}

                 exit;

               end;{endIfKey#1|StartUp}

 

      {SET RGB|HSB — BYa3digitNumber|0..255:}

         if (Shift=[ssAlt])then

         begin

           if KeyNP09=False then S:='';

           if(Key in [VK_NUMPAD0..VK_NUMPAD9])then

           begin

             KeyNP09:=True;

      {NumPad0..9 = 0..9|C h r Eller C h a r OK|vilketsom:}

             if not(Chr(Ord(Key) - 48) in ['0'..'9'])then

             begin

               //Label1.Caption:= 'ErrorInputChar|0..9|';

               exit;

             end;

             S:= S + Chr(Ord(Key) - 48);

             A:= StrToInt(S);

             if A>=255 then A:=255;

             Label1.Caption:= IntToStr(A);

      {EXECUTEnewValue:}

             if Length(S)=3 then

             begin

               S:= '';

               SetRoW(0,A);

               KeyNP09:=False;

             end;

             exit;

           end else exit;

         end;{endIfAlt}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

      {SETecSTEP|SlideSteps|Ctrl+NumPad|1|2|3|:}

         if (Shift=[ssCtrl])and(Key in [VK_NUMPAD1..VK_NUMPAD3]) then

         begin

           {                             1  2  3  }

           {NumPad|1|2|3|=|97|98|99| — | 1| 5|20|:}

           case Key of

             Ord(97): ecStep:= 1;

             Ord(98): ecStep:= 5;

             Ord(99): ecStep:= 20;

           end;

           exit;

         end;

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

         if Shift=[] then

         begin

              case Key of

         Ord('R'): begin

                     Pan60SetUp(ColFG);

                     exit;

                   end;

 

              end;{endCaseKey}

               {SWITCH|RGBside|HSBside:}

                  if Key=VK_CAPITAL then

               {kC=0|1 ¦ 0=RGBside | 1=HSBside:}

                  begin

                    SwitchSide(kC);

                    kC:= Abs(kC-1);

               {UPDATE|AnnarsFöregåendeKolumnsBokstav:}

                    SelRow(0,kC);

                    exit;

                  end;{endIfCAP}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

               {SelectROW|RGB|HSB:}

                  if Key in [VK_UP,VK_DOWN] then

                  begin

                    if Key = VK_UP then A:= -1 else A:= 1;

                    SelRow(A,kC);

                    exit;

                  end;{endIfUpDown}

               {EditRow|RGB|HSB:}

                  if Key in [VK_LEFT,VK_RIGHT] then

                  begin

                    if (Key = VK_LEFT) then A:=-1 else A:=+1;

                    SetRow(A);

                    exit;

                  end;{endIfLeftRight}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

         {FINALIZE|Status36=1|Pan60|EditColors|ZoomPlusInitiate:}

                  if (Key in [Ord('C'),Ord('O'),VK_ESCAPE,VK_RETURN])and(ecPanON)then

                  begin

         {========}

          Final:

         {========}

         {Hit om NumPad5 igen = Escape:}

                     ecPanON:=False;

                     Panel12.Hide;

                     ecTimer.Enabled:= False;

                     if(Key in [VK_ESCAPE,Ord('C')])then exit;

         {Key=Enter|O|SetSelectedColor|N=Förgrund Pan10|B=bakgrund Pan9:}

                     if FBflag='N' then begin

                       Panel10.Color:= eCol;

                       fgCol:= eCol;

                     end

                     else begin

                       Panel9.Color:= eCol;

                       bgCol:= eCol;

                     end;

                  end;{endIfEscEnter}

         end;{endIfNoShift}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

{Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·Oo°.·}

end;{endWithForm1}

end;{endEditColors|Från T2014 17Sep2014}

 

{ActualPROCEDURES & Functions - - - - - - - - - - - - - - - - - - -}

end.

ecU1C, END.

 

 

 

PhotoHSB, HueSaturationBrightness

 

26Sep2014-09-26

Ctrl+F2 — vi använder inte den delen Unit1A PhotoHSB från nu.

 

Insättningen av HSB-panelen med test på FOTOBILDER blev en STOR besvikelse:

 

1. Fruktansvärt långsam: 23-tumsskärmen på över två sekunder — för varje ändring i de 12 olika parametervärdena VmH|HSB|%;

2. AVGRÄNSNINGARNA i de olika HSB-regionerna MOTSVARAR INTE FÖRVÄNTNINGEN att kunna redigera FOTOBILDER på något ENHETLIGT TILLFREDSSTÄLLANDE sätt:

— PANORERINGSGränserna V|H åstadkommer delvis FULA FÄRGFÄLT som delvis demolerar HELHETEN:

— Hela METODFORMEN är tydligen INTE tillägnad någon översvallande FOTOGRAFISK FÄRGredigering.

   Nedslående. Vi hade hoppas (mycket) på HSB-panelen. Men den försvann i en dimma av mörker och dödande långsamhet.

3. YTTERST KOMPLICERAD KOMBINATORIK mellan de 12 olika parameterställena — trots enkel manövrering via tangenter VHMP|Pilar NP|1235: ytterst svåröverskådligt OCH MED MAGRA RESULTAT ÖVERLAG. Bu. Bu. Bu. Dåligt. Dåligt. Dåligt.

 

Zoom- och HSB-redigering verkar vara datorområdets allra svåraste detaljer att hantera — MED ACCEPTABELT TILLFREDSSTÄLLANDE RESULTAT (resultat som garanterat ligger på FRAMSIDAN om det man inte blir irriterad på).

 

 

 

AntecknatNatur, RamToning

 

2014-09-22

 

Det enda som behövs är det här:

— »VI ANSER INTE ATT VÅR VERKSAMHET MEDFÖR NÅGON ALLMÄN FÖRSTÖRING AV NATURVÄRDEN».

 

Foto:  27Aug2014  E18  Bild94 — Jesustrakasserier — ekande hånflabb — noll naturvett — StadsKärnansNyaPlanteringar — avhuggningar, sönderslitningar, öppna blödande natursår

 

TYDLIGEN: Den enda som vinner på verksamheten: våldet, våldets vidare utbredning, förebilderna för omdömet, omsorgen, omvårdnaden, föreställningen om sundhet och skick.

— Nämn NAMNET på den ETABLERADE ERKÄNDA NATURKRAFT som MOTSÄTTER SIG DEN UTVECKLINGEN: inte ett knäpp. Inte ett knyst. Inte ett ord. Ingen säger något.

 

Säg det. I klartext.

— »VI ANSER INTE ATT VÅR VERKSAMHET EFTERLÄMNAR INTRYCK AV VANVÅRD, OMDÖMESLÖSHET, OSKICK OCH OSUNDHET».

 

Där ögat tidigare möttes av naturfröjd, glädje, upprymdhet och vilsamhet, återstår bara en vy av bedrövelse, vanvård, missaktning och tydligt utövat djupt naturförakt. Kilometer efter kilometer. Mil efter mil. Varenda trafikled, vare sig asfalterad eller inte. JävlaNoga. Jag tänker inte cykla omkring i den starkt deprimerande miljön längre. Jag vägrar.

 

Jag vill mena det:

— Det existerar inget HÅLLBART STATLIGT ARGUMENT för ovanstående — men jag är övertygad om att ALLA STATLIGT ANSVARIGA KOMMER ATT FÖRSÖKA INBILLA EN SÅDANA. OM jag skulle vara den enda återstående överlevande naturvännen, är det i så fall en fajt jag måste ta med mina motståndare: Staten. Kommunen. Då kanske vi också för första gången får veta beslutsunderlaget för den uppenbara vandaliseringen i svart på vitt. Inget prat. Inget »å då ska du prata med den och den». Lärbart. Inget munväder. Ingen Privat LokalHerre som kör med GeniKontoret i PrivatFickan.

   Inledning:

— DEMOKRATI är fria val under mänskliga rättigheter. Inte under tillhyggesinrättningar. Det är grundläggande för naturvettet. Och vad jag vet, står det OREPRESENTERAT i landsänden: Sveriges dödspsykningar mot våldsvägrare under 150 år: polis, åklagare, domare, och på senare tid även allmänheten får vara med i festligheterna att trakassera och misshandla noll hotbild. Eftersom Naturen är min Läromästare, har jag ingen annan rationell och logisk grund att hänvisa till i min uppenbara, starkt, avvikande uppfattning mot allmänheten och dess allmänna våldsvägrarhat. Det är precis vad hela saken handlar om, min mening.

 

UR HÄLSOSYNPUNKT ÄR MOTSTÄLLNINGEN REDAN AVGJORD — min egen högst personliga erfarenhet: läromästare Naturen (medfött tjejvett): man gör inte så här. Det finns inget försvar för SÄTTET och VERKSAMHETEN — och heller ingen information i samband med ingreppens omfattning. Visa mig gärna motargumenten. Visa att jag har FEL, så ska jag alldeles tveklöst absolut ÄNDRA MIN INSTÄLLNING: Det vore jädrans KUL att få höra samma mening från motståndarlägret. Därför nämligen: jag tror inte ett ögonblick på att det är DEN föresatsen Man har: Hela saken gäller en ÖVERHETENS MAKTANSPRÅK. Inget annat. Noll ansvar. Noll information. DET vore upplyftande att få se närmare: DU HAR FEL.

 

 

 

Staten/kommunernas pågående naturvandalisering

— 2010-2014-

 

Det är uppenbart att de ansvariga i stat och kommun som numera — sedan runt 2010 — anställer omfattande systematiska naturavverkningar utan minsta försök att KOMPENSERA FÖR DEN UTEBLIVNA UTSIKTEN inte förstår vad det är man här håller på med. Låt mig försöka förklara den ståndpunkten på följande bekanta sätt.

 

Hur vet man, och på vilket sätt kan man förstå att stat och kommun här begår brott mot mänskligheten (A18: ”Var och en har rätt till frihet i tanke, samvete och religion ...”: tankefriheten är uppenbarligen att förstå som fullkomligt värdelös om dess uppbärande naturgrunder — naturansiktets naturligt orörda form som grund för uppfattningen om hälsa och välbefinnande — vanställs systematiskt; ”... att uppenbara sin religion eller tro i undervisning, utövande, andakt och iakttagande”; A19 ”Var och en har rätt till frihet i mening och uttryck ...”; A20.1: ”Var och en har rätt till oberoende fredlig samvaro och tanke.”; A20.2Ingen får tvingas tillhöra en sammanslutning.”; A22: ”Var och en, som en medlem av samhället, har rätt till ... och är berättigad att tillerkännas, genom nationella insatser och internationellt samarbete och i enlighet med organisation och resurser i varje Stat, de ... kulturella rätter som är oundgängliga för hans värdighet och den fria utvecklingen av hans personlighet”; A24: ”Var och en har rätt till vila och fritid”; I VAD exakt DÅ FÖR NÅGOT?;)?

 

Man kan veta det och förstå det på följande ytterst enkla grund: medfött tjejvett. Nämligen

med TJEJERNA SOM FÖREBILD — universums snyggaste och mest välformade, attraktiva och tilldragande varelser:

 

Naturen — skönheten, sundheten, friskheten, njutbarheten — har utvecklats på ORÖRD natur:

— NaturVärdet och NaturVården, med tjejernas formexistens som främsta konkreta exempel på det mest berikande, hälsobefrämjande, rekreationsgynnande, freds- och fridsamhetsbevarande — ligger tveklöst just i ORÖRD NATUR: där stat och kommun garanterat INTE har varit och sågat:

— att låta naturen få växa IFRED:

— att INTE TA BORT något:

 

Och?

 

TAR MAN BORT NÅGOT — t.ex. för bebyggelse — STRÄVAR MAN ATT FÖRSÖKA KOMPENSERA BORTTAGET GENOM ATT INRÄTTA — planera och plantera — MOTSVARANDE HARMONIERANDE INSLAG. Då fungerar det: Man strävar att GE tillbaka lika mycket som man TAR. Medfött tjejvett. Omsorg. Omvårdnad.

 

MEDFÖTT TJEVETT GÅR INTE UT I BUSKARNA, SÅGAR NER LEVANDE, OCH LÅTER RESTERNA LIGGA KVAR.

 

Medan det förra tillhör begreppet KULTUR och VETTIG CIVILISATION tillhör det senare alldeles tydligt, klart och omisskänneligt naturvandalisering: vandaliseringen SKAPAR INTRYCK AV TYNGD, OFRIHET, OHÄLSA, OTILLFREDSSTÄLLELSE, KRAFTLÖSHET, FÖREBILD FÖR ANSVARSLÖSHET, NATURFÖRAKT OCH ALLMÄN BRIST PÅ OMDÖME: sjukdom. Visa att jag har fel. DET samhället är på väg NERÅT i exakt samma takt. Medfött tjejvett befinner sig på kollisionskurs med Det samhället: våldet ökar. otryggheten ökar, vantrivseln ökar I EXAKT SAMMA TAKT SOM — orörd natur: medfött tjejvett — FÖREBILDEN FÖR SUNDHET, ORDNING OCH SKICK VANDALISERAS.

 

Så:

 

Säg den Internationella, Europeiska eller LokalStatiga eller Kommunala Instans som INTE instämmer.

 

Därför, att OM det finns en sådan instans, är det tydligen krigstillstånd som gäller: mänskligheten befinner sig under intrång och ockupation från naturföraktande, hälsoförstörande krafter och därmed direkt sjukdomsbefrämjande: otryggheten ökar.

 

 

 

 

ImportExport: 9Sep2022

 

GENERAL IMAGE HANDLING IN Delphi4Test2022

D4T — Delphi4Test2022

ImportExport

 

Import:

SCREEN

Directly from whole screen:

   PrtScn — PrintScreen — copies to ClipBoard

Directly from active window:

   Alt+PrtScn — copies to ClipBoard

CLIPBOARD

From ClipBoard:

   Ctrl+V

— Applies to both text (into an input text box) and image (directly into Delphi4Test2022):

— If ClipBoard has text only, and Image1 has focus on a Ctrl+V command

— as is normal in D4T

— a Ctrl+V results in a message box with information:

 

Export:

D4T has no save function — and no regret function (except Delphi4 text boxes).

   Perfect for memory training — and training »elimination of crappy decisions».

Works done in D4T are preferentially saved in Windows standard Paint — allowing its different manifold of file image formats.

 

 

   Preferably in general (for archive purposes) the PNG-format is the most memory saving alternative — if we wish to save and return to exact bitmap representations:

   The PNG format is the same as the RGB (24bit) image color format.

   The only difference is that true RGB saves one 24bit for each image pixel, the entire screen, while PNG collects only the number of used colors on the same principal RGB basis: PNG saves memory space.

   The JPG format is »reduced PNG color format»:

— JPG saves even more memory space — by reducing the number of (adjacent) image colors.

   Meaning:

   JPG is (mostly) good for photo images: the JPG reduction in PNG colors is (mostly) not visually recognizable — but can sometimes bee disturbing (if special colored text parts are included: these may lose some originality).

FormatPaint:

Keys

   Alt+F,E 1 TAB 1 Enter

sets the Paint image format to 1×1 pixel:

   The moment Paint receives a picture import from ClipBoard, Paint automatically adopts that picture’s metrics Width-Height.

 

Exporting images to Paint on equal or larger size, Paint always adopts automatically to the largest. Resizing (Alt+F,E 1 TAB 1 Enter) is only necessary if a smaller Paint copy is wanted.

 

   Repeatedly saving an image format from D4T by Ctrl+i, then becomes a simple importing procedure to Paint by keys

   Ctrl+i from D4T exports the whole present D4T image area picture to ClipBoard,

   Shift Windows focus (Alt+TAB) to Paint,

   Ctrl+V imports the picture to Paint.

SaveToPaint:

On first save, Paint want to know where — and on what image format. With these selected once, any repeated call to Paint for repeated savings on the D4T image workings will follow the simple key routine:

   Ctrl+i, Alt+TAB, Ctrl+V,S — and Alt+TAB back to D4T to continue the work.

 

Windows Paint is (hence) used as a (safe) image work copy backup — provided we are sufficiently observant to make a saveToPaint before we make some changes in D4T’s image area. IF we don’t, we’re smoked: D4T has no memory backup during our work — except Paint, or directly to ClipBoard with a Ctrl+i (whole image area) or a Ctrl+C to ClipBoard on a Mouse-drawn marked area.

 

RecalFromPaint:

Recall (last work) from Paint by clicking its left top icon area:

 

Paint opens the image area on all last saved selections.

— Or open the picture from (a personally reserved) picture archive folder with Paint.

   When Paint opens the picture, it has the metrics Width-Height last saved.

ImportingThePaintPicture:

With the Paint Window focused:

   Ctrl+A,C — then Alt+TAB to D4T and import the Paint picture with Ctrl+V.

— Ctrl+A selects ALL in Paint, C (with Alt-key still pressed) copies to Clip.

   Option in D4T is (Window size adoption)

   Key F5:

   The D4T Image area is always adopted to the last Clip imported image xy-size

 

on function key F5 [general UpDateFunction in some programs]

— with a few pixels addition on Width and Height for a minor margin (we sometimes add dates [D4T text-Function, Key (Ctrl+) T] in D4T-works to the Paint imported and others — right/above/below).

 

Exact adoption without additional margins have representation in the D4T Co-working Windows API developed programs BaseTextZ and PlainTextIm (BasicTextIm).

 

   With a minor adjustment on Windows size (Alt+Space), its precise pixel settings function (Ctrl+Arrows), this D4T key F5 option is useful in cases when we wish to repeatedly construct and present images on one and a same xy-size.

 

http://www.universumshistoria.se/zGMR2022.htm#ResNat1

 

 

For the sake of arguments:

 

— See also

TechnologyWindow

 

 

 

 

content:

innehåll: SÖK på denna sida Ctrl+F

 

 

 

DELPHI4Test2011

ämnesrubriker

 

innehåll

          DELPHI4 Programming Manual Examples

Föregående:

                         DELPHI4Test2011.htm — huvuddokument — HJÄLPDOKUMENT FÖR DELPHI4Test2011

 

                                      DELPHI4Test2011ref.htm — kompletterande

 

                         DELPHI4Test2011HELP.htm — särskild beskrivning

 

 

General image handling

 

 

                                      Elementär flytBilds Teknik

 

                                      DelphiBegin — Swedish archive edition 2011

 

                                      DelphiKod

 

                                      Programfönstret

 

                                      Komponenter

 

                                      ProjektKatalogen

 

                                      ExeIcon

 

                                      Label1

 

                                      Programenheter

 

                                      Caption

 

                                      BildKODteknik

 

                                      Alla4

 

                                      Peken

 

                                      LoadCursors

 

                                      CtrlV

 

                                      Resultat1

 

                                      FlytBildsTEKNIK

 

                                      F5 — Fönsteranpassning

 

                                      BildEXPORT

 

                                      PilotDISPLAY

 

                                      CursAcc

 

                                      Resultat2

 

                                      Flytbilden

 

                                      RitaMusHöger

 

                                      ArrowSwap — MoveMore

 

                                      MultiWin — flera öppna fönster

 

                                      Flytsätten

 

                                      FärgDisplay

 

                                      BGOFbegin

 

                                      BGOF — BakgrundsOberoendeFlytbild

 

                                      BGOFex

 

                                      Invertera

 

                                      RGBpalett

 

                                      Fel1664

 

                                      TBMIH — TBitMapInfoHeader

 

                                      FH — FlipHorizontal

 

                                      ExRgB

 

                                      TMrot90

 

                                      EditColors

 

                                      Unit1A —UnitRUBRIKERNA

 

                                      StreckRekt

 

                                      ClipCurs

 

                                      StreckRektStädKod

 

                                      StreckRektSynk

 

                                      StreckRektCurFlag

 

                                      StreckRektFlagIco

 

                                      kPD — PROGRAMDIVERGENS

 

                                      HELP

 

                                      HELPex

 

                                      Pan11F1

 

                                      HIMRV — vändHV roteraR inverteraI

 

                                      TabellHIMRV

 

                                      Zoom

 

                                      HastighetstestZoom

 

                                      VertSLtest

 

                                      VertTMStest

 

                                      WriteText

 

                                      TextIn

 

                                      TextInKOD

 

                                      RamToning

 

                                      NaturenRef

 

                                      FrågaNaturen

 

                                      SvarNV

 

                                      ComDo — CommanderDoit

 

                                      ecU1C — EditColors P2 DelphiKoden

 

                                      PhotoHSB

 

                                      AntecknatNatur

 

 

ImportExport

 

 

                                      content

 

 

 

 

referenser

 

 

 

 

Senast uppdaterade version: 2022-09-10.

*END.

Stavningskontrollerat 2011-06-08 (väl illa i så fall ..). Bättre 8Feb2022 (Från 1664-felet till hit — en timme senare: hela [jag måtte ha sovit vid första kollen 2011 ..]).

 

rester

*

 

DELPHI4Test2014MANUAL ·

 

 

√ τ π ħ ε UNICODE — ofta använda tecken i matematiskt-tekniskt-naturvetenskapliga beskrivningar

σ ρ ν ν π τ γ λ η ≠ √ ħ ω → ∞ ≡

Ω Φ Ψ Σ Π Ξ Λ Θ Δ  

α β γ δ ε λ θ κ π ρ τ φ ϕ σ ω ϖ ∏ √ ∑ ∂ ∆ ∫ ≤ ≈ ≥ ˂ ˃ ˂ ˃ ← ↑ → ∞ 

ϑ ζ ξ

Pilsymboler, direkt via tangentbordet: Alt+24 ↑; Alt+25 ↓; Alt+26 →; Alt+27 ←; Alt+22 ▬

Alt+23 ↨ — även Alt+18 ↕; Alt+29 ↔

Alt+1 →:

☺☻♥♦♣♠•◘○◙♂♀♫☼►◄↕‼¶ -20:

§▬↨↑↓→←∟↔▲▼ !”#$%&’(   -40:

 

 

DELPHI4Test2011.htm

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Senast uppdaterade version: 10 september 2022 |  14:49:20 | 2022-09-10. [GMT+1]Solar[GMT+2]Industry

 

 

Vidareutvecklat Från DELPHI 4 Test 2011 —  DELPHI4Test2011ref.htm#AnvändningSupportInstallation

T2014Reg — HUVUDDELEN AV VERKTYGEN MAN BEHÖVER FÖR AVANCERAD DATORANVÄNDNING I TEXT OCH BILD ¦ Jan2022

 

*