Keresés

Új hozzászólás Aktív témák

  • vz12

    tag

    válasz Tomi_78 #2142 üzenetére

    Hááát, szerintem a help-ben benne kellene lennie a kódoknak, vagy a Google is segít, pl. a "Delphi key codes" keresése után, rengeteg találat van.
    Ha a numerikus kódokat saját szemeddel akarod látni, akkor pl. az OnKeyDown bemenő paramétereit írasd ki, ezeket el is tudod tárolni, mondjuk egy INI fájlban, majd később ezeket vissza is tudod olvasni, szövegből numerikus típussá alakítva vizsgálni is tudod. A régebbi Delphi-kben ez WORD típus, az újakban nem tudom. Kis/nagybetűkre figyelj.

  • vz12

    tag

    válasz Tomi_78 #2139 üzenetére

    > ujkep.pixelformat:=pf32bit;

    Az előző válaszomban lévő első sorban a "spéci" linken lévő megoldásnak is ez a lényege.
    Örülök, hogy örülsz, jó érzés megtalálni a megoldást egy problémára. :)

  • vz12

    tag

    válasz Tomi_78 #2137 üzenetére

    Itt van valami spéci megoldás Lazarus-ra (PNG): [link]

    Ha a Lazarusban van "TPNGImage", az máris megoldhatja, a régebbi Delphi-kben ez külső library lehetőségként megvolt, az újabbakban talán már benne van.

    Egyébként Google :), én sosem csináltam ilyet.

  • vz12

    tag

    válasz Tomi_78 #2134 üzenetére

    Nos, nem nagyon értek hozzá, de nem gondolnám, hogy csupán property-k állítgatásával újraÉPÍTI (konvertálja) a kép tartalmát, ezért menthette az eredeti képet. A property-k a vizualitásra hatással lehetnek, de BELÜL a kép szerintem NEM változik.

    Ezen link alapján (ott "procedure TForm1.Button2Click(Sender: TObject);") írtam egy egyszerű működő példát Delphi-ben, még a képernyőn sem jelenítettem meg semmit (a gombon kívül), csak gombnyomásra legyártja egy kép kicsinyített mását a méretarány megtartásával.
    1280x905 helyett 100x71 pixel.
    672 Kb helyett 5 Kb.
    Ja, a példa JPG-vel dolgozik, tehát JPG-ből JPG-t csinál (a köztes állapot BMP).
    Ha fontos a PNG, azt Te nyomozd ki.

    procedure TForm1.Button1Click(Sender: TObject);
    var Source: TJPEGImage;  Dest,Temp: TBitmap;
    begin
      Source:=TJpegImage.Create;
      try
        Dest:=TBitmap.Create;
        try
          Temp:=TBitmap.Create;
          try
            Source.LoadFromFile('VALAMI.JPG');
            Source.DIBNeeded;
            Dest.Assign(Source);
            Temp.width:=100;
          Temp.height:=Round(Source.height*(Temp.width/Source.width));
            Temp.Canvas.StretchDraw(Rect(0,0,Temp.width,Temp.height), Dest);
            Source.Assign(Temp);
            Source.SaveToFile('PROBA.JPG');
          finally
            Temp.Free;
          end;
        finally
          Dest.Free;
        end;
      finally
        Source.Free;
      end;
    end;

    A "Temp.SetSize()" nálam nem működött, azért változtattam meg.
    Olyan sok képformátumot NEM kezel a Delphi/Lazarus, tehát egy "általános" képkonvertáló program írására a fenti egyszerű módszerrel nem lehet messzire jutni.
    Kép méretezésre jó lehet JPG, BMP esetén.

  • vz12

    tag

    válasz Tomi_78 #2132 üzenetére

    Szerintem az baj, bizony.
    Én a FormCreate-be tettem, illetve a programozott létrehozásokat, valamint a kezdeti beállításokat a fő formra vonatkozóan mindig odateszem.
    Legfeljebb ELREJTEM addig, amíg nem kell.

    Ahogy látom, a "jatallapot=2" esetén lehet, hogy elég sokszor létrehozza azt a gombot és esetleg besokall a gép, persze nem ismerem a vezérlésedet, de onnan tedd át máshova gyorsan, ami garantáltan egyszer fut le, pl. a FormCreate-be.

  • vz12

    tag

    válasz Tomi_78 #2129 üzenetére

    Hát, nem tudok mit mondani, vettem a fáradtságot, és LAZARUS-ban kipróbáltam, mielőtt beküldtem ide, és nálam működött.

    A form "KeyDown"-ja valóban a "FormKeyDown" eljárásra mutat? Nálad is az a neve? Nem változtattad meg? Mert ha igen, akkor a megváltoztatott eljárás nevet kell odaírni a vastagbetűs sorba, de ez triviális.

    Nem tudom, hogy mi a problémája a pupup menüvel, meg hogy milyen töréspontokról van szó, meg hogy milyen köze van a "keydown"-hoz, szerintem semmi.

  • vz12

    tag

    válasz Tomi_78 #2128 üzenetére

    "Focus is the ability to receive user input through the mouse or keyboard. Only the object that has the focus can receive a keyboard event. Also, only one component per form can be active, or have the focus, in a running application at any given time.
    Some components, such as TImage, TPaintBox, TPanel and TLabel cannot receive focus. In general, components derived from TGraphicControl are unable to receive focus. Additionally, components that are invisible at run time (TTimer) cannot receive focus."
    -----------------
    Itt van még valami:
    To trap keystrokes at the form level instead of passing them to the form's components, set the form's KeyPreview property to True (using the Object Inspector). The component still sees the event, but the form has an opportunity to handle it first - to allow or disallow some keys to be pressed, for example.

    Magát a formot közvetlenül NEM bill. inputra tervezték (az a rátehető objektumok egy részének a feladata), de eseménykezelője van, a form csak úgy figyel a háttérben.

    Ha a formon beállítod a "KeyPreview=true"-t, akkor ELSŐDLEGESEN (központosítva) a form eseménykezelője dolgozza fel a bill. eseményeket, pl. a keydown-t is, MAJD AZUTÁN annak az objektumnak (pl. gombnak) a pl. keydown-ja is lefut, ahonnan a bill. lenyomás érkezett. A sorrend fontos, a form eseményben trükközni is lehet, mielőtt az objektum feldolgozná a bill. nyomást.

    Ha a "KeyPreview=false", akkor a form bill. kezelő eseményei hatástalanok (ez történt nálad is, mert a "false" az alapértelmezett). Ilyenkor az általam írt "központosítás", mint módszer/trükk használható, tehát a formon lévő OBJEKTUM eseménykezelője kapja el a bill. nyomást (mert a formé nem fogja), de a form eseménykezelője hajtra végre. Ez jó akkor, ha pl. nem akarod, hogy minden objektum esetén végrehajtódjon a "központi" kód, csak azoknál amelyeknél beállítod, illetve nem akarsz többszörösen (redundánsan) kódolni.

    A gyakorlatban: (a kilepgomb.OnKeyDown ki van kommentelve)

    form1.KeyPreview:=true;
    kilepgomb:=TButton.Create(form1);
    kilepgomb.Parent:=form1;
    kilepgomb.Top:=2;
    kilepgomb.Left:=2;
    kilepgomb.Caption:='Esc';
    // kilepgomb.OnKeyDown:=@FormKeyDown;
    kilepgomb.OnClick:=@kilepgombkatt;

  • vz12

    tag

    válasz Tomi_78 #2126 üzenetére

    kilepgomb:=TButton.Create(form1);
    kilepgomb.Parent:=form1;
    kilepgomb.Top:=2;
    kilepgomb.Left:=2;
    kilepgomb.Caption:='Esc';
    kilepgomb.OnKeyDown:=@FormKeyDown;
    kilepgomb.OnClick:=@kilepgombkatt;

    Amikor a kilépés gombon állsz, akkor nem aktív a form, vagyis a bill. lenyomás NEM a form keydown-ja, hanem a button keydown-ja.
    Pl. a fenti módon át lehet irányítani az eseményeket, így "közös" keydown-ja lesz a gombnak és a formnak.
    :)

  • vz12

    tag

    válasz Tomi_78 #2124 üzenetére

    Nincs mit. :)
    Valóban nem könnyű, és ezt a "civilek" legtöbbször nem látják, sokszor téves elképzeléseik vannak magáról a feladatról is, meg annak adott körülmények közötti megvalósításáról is, pl. időigény, stb. Az még a legszerencsésebb helyzet, ha az ember "nyomás nélkül" saját magának írja a programot, és van rá elég ideje meg elhivatottsága is.

  • vz12

    tag

    válasz Tomi_78 #2122 üzenetére

    Nagyon jó változtatásnak tűnik a "letezik" helyett a "nil"-re vizsgálni, jó ötlet volt. :K

    > a FreeAndNil() nem azonnal töröl?
    A neve alapján illene azonnal törölnie.
    Ezt találtam gyorsan róla a neten: It calls an object's destructor
    Vagyis elvileg valóban töröl, megsemmisít, de többet erről csak az tud, aki írta a forráskódját ...

    Ha tényleg megszűntek a hibák, akkor "megérte" ennyit foglalkozni vele, valószínűleg sokáig megmaradó tapasztalatot szereztél vele, csak így tovább.

  • vz12

    tag

    válasz Tomi_78 #2118 üzenetére

    Nos, ha timer-rel frissíted "valamikor" a pályát MIKÖZBEN esetleg a törlések éppen zajlanak, az nem tűnik szerencsésnek. Itt valamilyen minimális szervezésnek illene lennie, pl. egy logikai változónak, hogy éppen "karbantartás" zajlik, ilyenkor a frissítés legyen blokkolva. A karbantartás végeztével a logikai változó megváltozásával ismét mehet a frissítés. Tehát a törlések UTÁN a megváltozott állapotra kell ráengedni a frissítést.

    Esetleg - ez még jobb - lehet 2 db logikai változó is, oda-vissza ellenőrzéssel, addig nincs frissítés, amíg karbantartás van, illetve addig nem kezdődik karbantartás, amíg zajlik a frissítés.

    Mondom ezt csak ötletként, a pontos kód ismerete nélkül, de amúgy lehet, hogy eddig is ez az egyidejűség okozta a problémádat.
    Ezek a változók lennének az ún. "szemafor"-ok, ennek van hagyománya a programozásban, és kb. ilyen esetekben használják őket, az egyidejűség elkerülésére, hogy ne legyen "karambol".

  • vz12

    tag

    válasz Tomi_78 #2114 üzenetére

    > "Cannot find bounds of current function"
    És van a függvénynek eleje/vége? El sem kellene indulnia a programnak, ha ilyen hiba van benne, ez az üzenet számomra nagyon furcsa, gyakorlatilag értelmezhetetlen.

    > F9-re is ezt írja ki
    Újraindítás után, MIELŐTT F9-et nyomnál, próbáld meg törölni az összes töréspontot:
    Nézet/Hibakereső ablakok/Töréspontok (Ctrl+Alt+B)
    Nyilván itt ki kellene jelölni az összes töréspontot, majd törlés.
    Ha utána sikeresen elindul, akkor - ha még nem ment el a kedved tőle - meg lehet próbálni a futtatást.
    A Shift+Ctrl+F9-cel a "Futtatás/Futtatás hibakeresés nélkül" esetén elvileg szintén nem szabadna annak a csúnya "Hibakereső Hiba" ablaknak megjelennie, hiszen nincs hibakeresés. De ez már lehet hogy egy Lazarus hozzáértő segítségét kívánja.
    Ha "megjavult", akkor ÉN nagyon óvatosan (messziről haladva, egyesével, vagy csupán csak 1-et) megpróbálnám újra felvenni a törésponto(ka)t.
    Akkor tudok ilyen hiba ablakot esetleg elképzelni, ha a töréspont a hiba UTÁN lett téve, és a hiba hatására valamilyen kezelhetelen állapotban beragadt a Lazarus.
    Bízom benne, hogy teljes újratelepítés NEM szükséges, mert az durva lenne.
    Sosem voltam ilyen helyzetben, tehát ezt nem tudom.

  • vz12

    tag

    válasz Tomi_78 #2110 üzenetére

    Hello!

    A pontos választ nem tudom, de gyors kereséssel az alábbi lehetséges okokat dobta a Google:

    If a program gets a segmentation fault (SIGSEGV), it references a memory address outside of the memory available to it.
    The most frequent causes for a segmentation fault are:
    An array index is outside the declared range.
    The name of an array index is misspelled.
    The calling routine has a REAL argument, which the called routine has as INTEGER.
    An array index is miscalculated.
    The calling routine has fewer arguments than required.
    A pointer is used before it is defined.

    Valószínűleg ezek csak példák, tehát lehetséges más ok is, de kiindulási alapnak talán elegendő.
    A debugolást tessék megtanulni, nagyon leegyszerűsíti a hibakeresést, a Delphi-ben a beépített debugger nagyon egyszerűen és kiválóan működik, a Lazarus-ban lévő pedig a képek alapján kb. ugyanaz lehet.
    Az első G-s találat a "debug in Lazarus"-ra ez, ránéztem, tök jó:
    [link]

    Egyébként ezt a hibát NEM biztos, hogy lehetséges könnyű megtalálni, mert ha pl. iterációban, időzített futásban, stb., tehát ha NEM az első ráfutáskor, hanem később "menet közben valamikor egyszercsak" jelentkezik a probléma, a változók változásai miatt, vagy ha a debugolás miatti megállások megváltoztatják a környezeti (idő) feltételeket, akkor bizony rá kell szánni az időt. És neked még azt is be kell határolni, hogy vajon HOVA kellene töréspontot tenni (ahol - még egyszer mondom - lehet hogy az első N db alkalommal akár minden rendben is van, tehát hiába állítod meg ott a programot, csak utána romlik el ugyanott "valamikor"). Először az F8-akat kellene nyomkodni, és ha megvan, hogy miben száll el, akkor (elölről kezdve) ugyanott F8 HELYETT F7-tel kellene OTT mélyebbre menni, ahol 1-gyel mélyebb szinten először szintén F8, utána F7. Amikor már nem lehet mélyebbre menni (F7), akkor megtaláltad a hibapontot, és kiakadás előtt meg kell vizsgálni a változók, objektumok, tömbök, stb. tartalmait akár ezek "watch"-olásával, akár az egér sima elem fölé húzásával, ahogy a fenti videóban is mutatják, és a kiírt értékek alapján NEKED már látnod kellene a problémát.

    A fentiek alapján MEGELŐZÉSSEL is lehetne kísérletezni, brutál validációkkal (kissé túl erőltetettnek tűnő IF-ezéssel) a tömb indexek és a mutatók/pointerek felhasználását tekintve. A rossz függvény paraméterezést kevéssé tartom valószínű oknak, azt talán "rendesen" is meg tudja mondani a Lazarus, de ki tudja.
    Esetleg (de ez csak ötlet) ha képernyő/pálya frissítésével függ össze a hiba, akkor LEHET, hogy a megadott frissítési idő kevés, ezért "összetorlódnak" a feladatok, amit már nem bír elviselni a rendszer, vagyis próbálkozni lehet a frissítés idejének megnövelésével is VAGY a pályaméret csökkentésével VAGY a frissítéskor lefutó kód gyorsításával, amennyiben az még nem optimális.

  • vz12

    tag

    válasz Tomi_78 #2107 üzenetére

    Ezt leginkább csak debug-olással lehet kideríteni, nálad.
    Legyen egy töréspont az "if"-en, és sor léptetésekkel haladva le kell kérdezgetni a kérdéses adatokat. A számítógépnek biztos, hogy igaza van, vagyis valahol valamilyen érték nem fog stimmelni, onnan kell majd tovább nyomozni.

  • vz12

    tag

    válasz Tomi_78 #2105 üzenetére

    0. Meg kellene nézni (debug), hogy az "egysegek[edb]" véletlenül se legyen NULL. (valószínűleg nem az, de legyél teljesen biztos benne)

    1. Lehetne ezt a mintát követni, a "véletlen" problémák kivédése okán:
    if Assigned(x) then FreeAndNil(x);

    2. A fent említett mutatóra CAST-olnám a saját típusát, szintén csak a biztonság kedvéért, ez amúgy SOHASEM árt.
    / FreeAndNil(TDeklaráltTipus(egysegek[edb])); /

    3. Megpróbálnám ezt is, ez az "eredeti" pascal megoldás, 2 lépésből áll:
    dispose(TDeklaráltTipus(egysegek[edb]);
    egysegek[edb]:=nil;
    / Tudom, hogy a "FreeAndNil" is elvileg pontosan ezt csinálja, csak 1 lépésben, de azért gyakorlati tapasztalat szerzése céljából én kipróbálnám. /
    ---------------------
    Én a típuskényszerítéstől várnám a megoldást, mert a "sima Free" túl általánosnak tűnik, "mindenre" IS működnie kell, ezért valószínűleg sima "Pointer" vagy "TObject" hivatkozásokkal dolgozik.

  • vz12

    tag

    válasz Tomi_78 #2102 üzenetére

    Szuper!
    A kitartó kísérletezgetéssel rengeteg tapasztalatot lehet szerezni, ami tudássá tud alakulni és jó esetben még élvezi is az ember. :)

  • vz12

    tag

    válasz Tomi_78 #2098 üzenetére

    Szerintem a BMP nem tud átlátszó lenni, vagy igen?
    Halványan régről emlékszem olyanra, hogy ha a ".bmp" fájl mellett van egy ugyanolyan nevű ".msk" fájl IS (maszk fájl), akkor HA a szoftver fel van rá készítve, akkor az ".msk" fájl segítségével működhet az átlátszóság a BMP-nél is. Nem tudom, hogy a Delphi ismeri-e ezt a módszert, illetve van-e neked ".msk" fájlod.

    Véleményem szerint a TImage jobb lenne neked, mint a TBitmap, mert annak a "Picture.LoadFromFile"-ja több formátumot is kezel, pl. a PNG-t, ami viszont alapból átlátszó. A "transparent" property-t persze biztos true-ra kell állítani ilyenkor is.
    De ez csak egy ötlet volt.

  • vz12

    tag

    válasz Tomi_78 #2094 üzenetére

    Igen, a példában ugyanaz a "Canvas" volt a forrás és a cél is, de 2 db különböző "Canvas" között is működnie kell, amennyiben a méretük megfelelő.

    > tudtommal Delphi-ben van olyan függvény erre, hogy CopyRect(), de Lazarus-ban ezt nem találom
    > Mi a használatának a módja?

    Én csak "megtaláltam" neked, amit egy példával illusztráltam. :)
    Így talán hanyagolni lehet a "külső" képszerkesztőt. :K

  • vz12

    tag

    válasz Tomi_78 #2092 üzenetére

    Én úgy látom, hogy Lazarusban is úgy működik a CopyRect(), mint a Delphiben.
    Feltettem egy Lazarust, és kipróbáltam. :)
    Egy üres formra rátettem egy "TImage" elemet, és gyorsan írtam egy példakódot. Rajzoltam egy kört, és "CopyRect"-tel klónoztam:

    procedure TForm1.FormCreate(Sender: TObject);
    var r1,r2:TRect;
    begin
        Image1.left:=0;
        Image1.top:=0;
        Image1.width:=200;
        Image1.height:=100;;
        Image1.Canvas.pen.color:=clWhite;
        Image1.Canvas.brush.color:=clWhite;
        Image1.Canvas.Rectangle(0,0,200,100);
        Image1.Canvas.pen.color:=clRed;
        Image1.Canvas.brush.color:=clYellow;
        Image1.Canvas.Ellipse(0,0,100,100);
      r1.left:=0;   r1.top:=0; r1.right:=100; r1.bottom:=100;
        r2.left:=100; r2.top:=0; r2.right:=200; r2.bottom:=100;
        Image1.Canvas.CopyRect(r2,Image1.Canvas,r1);
    end;            

    Az eredmény 2 db kör egymás mellett, tehát működik. :)
    A CopyRect() szintaktikája talán egy kicsit furcsa, de meg lehet szokni, és pontosan olyan, mint Delphi-ben, nem látok különbséget.

  • vz12

    tag

    válasz Fire/SOUL/CD #2089 üzenetére

    > valami módot keresek arra, hogy ne kelljen minden menüponthoz külön függvényt írni

    Pontosan olyan megoldást javasoltál, amit el szeretett volna kerülni ...
    Ha sok menüpontnál hasonló vagy gyakorlatilag ugyanaz a kód kell, akkor nagyon is célszerű ezt összevonni, a kódismétlést ott kell kerülni, ahol csak lehet.
    Ha eltérőek a menüpontok kódjai (VAGY várható, hogy a jövőben el fognak térni ...), akkor persze érdemes külön-külön függvényeket/kódokat írni, ilyenkor a "tag"-ra nincs szükség.
    A "tag"-nak egyébként nem kötelező egyesével növekedni, a Longint miatt megoldható "beszédes" érték is, pl. a 324 lehet a 3. menüpont 2. almenüjének a 4. al-almenü végpontja, feltételezve, hogy egy szinten nincs 9 menüpontnál több.
    Ha több elem van 9-nél, akkor lehet 2 jegyből álló blokkokat is csinálni, pl. 1205 a 12. menüpont 5. almenüpontja, de a legfelső szinten a vezető nulla sajnos nem működik, ott lehet 3 jegyű blokk. pl. 90203 a 2. menüpont 3. almenüje (a kezdő 9-es figyelmen kívül hagyandó). Így 99 menüpont lehet szintenként, ami már elég kell, hogy legyen, legtöbbször a 9 is elegendő.
    Az ilyen "tagolt taggal" jobban átlátható a rendszer, persze egy nagyobb menü átalakítás után rendet kell csinálni a kódban, de bővítésre meglehetősen rugalmas ez a megoldás.

    És igen, a menürendszernek csak a "végpontjait" kell OnClick-elni (a menüfa LEVELEIT). :K

  • vz12

    tag

    válasz Tomi_78 #2086 üzenetére

    Szerintem az OnClick-nek csak "Sender" paramétere van, és nem lehet második paramétert használni. Az alul lévő megoldás egyébként megfelelő, de egy kicsit azért lehet javítani rajta.
    Hasonló, de talán egy kicsit szebb a Sender.tag használata, amit a property beállításoknál akár tervezési időben is meg lehet adni, de dinamikusan, kódból is. A "tag" viszont egész szám típusú (talán Longint), amit én 1,2,3, stb-re állítanék be (indulhat 0-tól is, de tudni kell, hogy alaphelyzetben minden objektumnál tag=0), amit úgy lehet a leghatékonyabban string típussá alakítani, ha definiálsz egy string típusú elemekből álló TÖMBÖT a programban 1,2,3, stb. tömbindexekkel. Az OnClick-ben pedig már csak használni kell a Tomb[Sender.tag] string értéket. :)
    Persze némi validáció (intervallumba tartozás vizsgálat) a tömbindexre (Sender.tag) nem árthat.

    Ja, természetesen a különböző elemek OnClickjébe ugyanazt a függvényt kell beállítani, a hívó objektum "tag" beállítása legyen csak különböző.

  • vz12

    tag

    válasz Tomi_78 #2081 üzenetére

    Igen.
    Pontosan olyan igényt fogalmaztál meg, amire pontosan a TPopupMenu a megoldás.

  • vz12

    tag

    válasz Tomi_78 #2078 üzenetére

    NEM "TMainMenu"-ről volt szó, hanem "TPopupMenu"-ről ...
    A főmenü helye valóban az ablak tetején egy teljes szélességű "csík", nézz meg bármilyen "normális" alkalmazást, neked NEM ez kell.
    Arról is volt szó, hogy TERVEZÉSI időben nyugodtan létre lehet hozni a popup menüt, alapból nem fog látszódni, csak egérkattintás utáni aktivizáláskor (kóddal), és automatikusan el is fog tűnni, vagy a menüpont kiválasztásakor (ilyenkor végrehajtja a mögé írt kódot is), vagy a menü területén kívüli kattintásra (ilyenkor nem csinál semmit). Az eltüntetés beépített feature, azt nem kell kódolni.
    Tervezési időben a megfelelő elemet (TPopupMenu) oda kell tenni a formra, és a beépített szerkesztővel fel lehet venni az elemeket + az OnClick eseményre lehet kódot írni szintén előzetesen. Futásidőben CSAK aktiválni kell az előre elkészített popup menüt, ami megjelenik + a fent említett esetekben automatikusan eltűnik, semmilyen "téglalap" nem marad utána.
    A korábban megadott linket érdemes tanulmányozni, vagy valamilyen hasonlót lehet keresni a neten, az meg fogja erősíteni az általunk írtakat.

    Ja , "mbRight" helyett neked "mbLeft" fog kelleni, így a BAL egérgomb kattintásra fog aktiválódni a popup menü.

  • vz12

    tag

    válasz Tomi_78 #2073 üzenetére

    Hello!

    Miért kell futásidőben létrehozni? Helyzettől függően változik a tartalma?
    Amúgy szerintem neked TPopupMenu kell inkább.
    Ennek van egy "items" property-je, ami tartalmazza az egyes menüpontok objektumait szépen sorban, és amelyikhez van "onclick", az végrehajtja az ottani kódot. Azt hiszem, hogy az egyes menüpontokat lehet "disabled/enabled" állapotba is tenni (valahogy), tehát én inkább tervezési időben rátenném a formra a popup menüt, meg az elemeit, meg az onclick-eket, futásidőben legfeljebb ki/bekapcsolgatnám a menüpontokat helyzettől függően.
    Vagy TÖBB popup menüt is lehet csinálni, és mindig a megfelelőt kell aktiválni.

    Én sosem használtam Lazarust, csak régebben "rendes" Delphi-t, de szerintem ez nem nagyon különbözhet egymástól.

    Találtam Lazarushoz linket:
    [link]

  • vz12

    tag

    válasz Tomi_78 #2066 üzenetére

    > Akkor a Pixels nemcsak lekérdezésre használható, de értéket is lehet neki adni?

    Én már használtam úgy, bár régen és NEM Lazarus-ban, hanem "normál" Delphi-ben, ott működött.
    Szerintem "illene" működni Lazarus-ban is. Próbáld ki. :)

  • vz12

    tag

    válasz Tomi_78 #2064 üzenetére

    > A színeket meg innen puskáztam ki: [link]
    A fehér ott sem $000000 ... :N
    De a "clWhite", "clBlue" az rendben van. :)

    Esetleg a
    "palyakep.canvas.fillrect(vsz,vm,vsz+1,vm+1);" helyett pl . a
    "palyakep.canvas.Pixels[vsz,vm]:=clWhite;" nem lenne szebb?

    A 3 db "random(100)"-at sokallom egy kicsit, de te látod az eredményt, ha jó, akkor jó.
    Remélem, hogy "Randomize;" van a program elején ...

  • vz12

    tag

    válasz Tomi_78 #2060 üzenetére

    Próbálj meg közvetlenül a "$" után írni 2 db "0"-t, tehát pl. TColor($00FF0000).
    Arra figyelni kell, hogy a színek sorrendje a "00" után NEM a normális "R-G-B", hanem "B-G-R", tehát fordított, viszont úgy látom, hogy ezt jól csináltad, legalábbis a KÉK szín esetén, a fehér viszont szerintem $00FFFFFF.

  • vz12

    tag

    válasz Tomi_78 #2058 üzenetére

    Örülök, hogy hasznát vetted az észrevételeimnek.
    Jó szórakozást, jó játékot! :)

  • vz12

    tag

    válasz Tomi_78 #2056 üzenetére

    Hello!

    > Akkor a SetSize csak kisebbíteni tud képet?
    Ahogyan írtam is, a "SetSize" nem nyújt sem össze, sem szét, nem vetít, nem projektál. Tehát NEM kicsinyíti/kisebbíti és NEM nagyítja/nagyobbítja a TELJES képet. Tegnap este nem volt és most sincs előttem Delphi, de az általad írtakból + a Google találatokból is azt látom, hogy a "SetSize" a képből VÁG, kimetszi a kép egy RÉSZÉT az eredeti méretben, ha tudja, de működik az eredeti képméretnél nagyobb értékekkel is (nem akad ki a program), csak ilyenkor információ hiányában alapértelmezetten fekete színnel tölti ki a plusz helyet. De működik. Biztosan van valami "stretch" lehetőség, csak be kell állítani, de ezt rád bízom. Egyszínű képeknél ez a nyújtás még nem is okoz problémát, "rendes" képeknél viszont akár nagyon csúnya is lehet az eredmény. Kísérletezgetni, "játszani" kell a dolgokkal, és rá fogsz jönni.

    >Ezt hogyan csináltad?
    Semmi extra, a képet megnyitottam Paint-ben, ahol az egérmutató (X,Y) pozíciója látszódott a státusz sorban, ebből könnyen kiszámítható volt, itt csak az X érték kellett. Ha jól emlékszem, a zöld sáv szélessége 86 pixel volt, a zöld+fekete sáv szélessége 135, az arányuk 86/135=0.637 (kb.), ami nagyon hasonlít a 256/400=0.64-re, csak a "durvább felbontás" miatt mondjuk kerekítési eltérés tapasztalható.

    Megoldás1: a "stretch" lehetőség megtalálása (vagy van, vagy nincs, fejből nem tudom, nekem még nem kellett)
    Megoldás2: 256*256-nál (lényegesen) nagyobb kép alkalmazása, hogy nagyobb form-on se jelenjenek meg a fekete sávok (egyébként "alul" is megjelenhetnek, ha olyanok a számok ...)

  • vz12

    tag

    válasz Tomi_78 #2054 üzenetére

    Hello!

    (1) pm-psz csere ("m" a magasság, "sz" a szélesség szeretne lenni (?))
    A tömbben az ELSŐ index az a SOR, a grafikán az ELSŐ koordináta az X pozíció, tehát az OSZLOP.
    A tömbben a MÁSODIK index az OSZLOP, a grafikán az MÁSODIK koordináta az Y pozíció, tehát az SOR.
    Ezért kell felcserélni.
    Továbbá, ha "pm"-et és "psz"-t jól értelmeztem fentebb, akkor a 2 db FOR ciklust szerintem fordítva értelmezted, bár a végeredmény szempontjából az mindegy, hogy balról jobbra + felülről lefelé haladva a SORokkal rajzolod ki, vagy felülről lefelé + balról jobbra haladva az OSZLOPokkal rajzolod ki.
    >psz=1 esetén 400*1=400-zal arrébb, és 800-nál van a vége (+400), stb. tehát elvileg mindig egymás mellett
    Mivel "psz" NÁLAD valójában NEM a "szélesség", hanem a "magasság", ezért a megfogalmazásodban a "mellett"-nek valójában "alatt"-nak kellene hogy legyen.

    (2) fekete csík
    Úgy látom, hogy a képernyő szélessége NEM egyezik meg a magassággal (szélesebb, mint amilyen magas), de a rajz elvileg mind a kettőt arányosítja (nagyon helyesen). A kiinduló képed 256*256-os ("NÉGYZET" alakú). A SetSize az eredetinél kisebb méretet minden probléma nélkül ki tudja venni a képből (eredeti tartalommal), de mit kezdjen a "hozzátoldással"? Úgy tűnik, hogy a Delphi fekete színnel (=0) bővíti a képet, amennyiben a SetSize paramétere nagyobb az eredeti méretnél. Te pedig VÍZSZINTES irányban bővítetted a képet 256-ról 400-ra, ezért lett a "toldás" fekete színű. Úgy tűnik hogy FÜGGŐLEGESEN belefértél a 256-ba, a képernyő arány miatt, ezért "folytonos" a kép függőlegesen, nem kellett fekete színnel kiegészíteni.
    A "SetSize" NEM nyújt, hanem kivág, legalábbis jelen esetben.
    ENNYI. :)
    Ja, és vettem a fáradságot, arányítottam a "zöld" sáv pixelben vett szélességét a "zöld+fekete" szélességhez, és kerekítéstől eltekintve egészen pontosan kijött a 256/400 arány.

    Az nagyon jó, hogy elegendő adatot írtál a problémához, kellett a megoldáshoz. :)

    Egyébként miért kellett megszorozni 2-vel a "Form1.width" és a "Form1.height" értékét? Hogy "lelógjon" a képed a képernyőről, vagyis a form-ról?

  • vz12

    tag

    válasz Tomi_78 #2042 üzenetére

    > úgy tudom, létezik egy "result" utasítás is Pascalban

    NEM UTASÍTÁS, hanem változó.
    Van amelyikben létezik, van amelyikben nem ... A "sima" pascalban tudtommal NEM létezik, a Delphiben létezik.
    Ha minél hordozhatóbb ("kompatibilis") kódot szeretnél írni, akkor NE használd a "result" változót, szerintem. Ha Delphin belül maradsz, akkor oké, de érdemes tudni a fenti információt.
    Amúgy a "result" egy olyan (lokális) változó, amit a fordító a függvény számára automatikusan deklarál, típusa a függvény visszatérési típusa, lokális változót a függvényekben ezzel a névvel (újra) deklarálni nem lehet, és "össze van drótozva" a függvénnyel, ha az egyik értéket kap, akkor azt a másik is megkapja, oda-vissza.
    Mivel változó, ezért értéket akárhányszor kaphat (ez is) a függvényben, ettől még a függvény működése NEM ér véget. Használatával akár "érthetetlen" kódot is lehet íni, nekem nem tetszik.
    Azt csinálsz amit gondolsz, de szerintem sokkal tisztább, érthetőbb és hordozhatóbb a kód, ha az általam javasolt SAJÁT lokális változót használod a "result" változó helyett.

  • vz12

    tag

    válasz Tomi_78 #2040 üzenetére

    Hello!

    > a függvény visszatérése a nevével nem fejezi be a ciklust is?

    NEM, az "csak" egy értékadó utasítás, és nem return. Ebből következik, hogy a függvény belül akárhányszor kaphat értéket, az utolsó értékadás a visszatérő érték. A példád szerinti kódban tehát az "utkitt" függvényed visszatérési értéke MINDIG false (!!!)
    Egyébként úgy lenne "szép". ha a függvényben egy lokális változót definiálnál a visszatérő érték számára, a függvény értékek menet közben ebbe kerülnének bele. Sokszor érdemes egy kezdeti értéket is adni neki, hogy ne érjen később meglepetés. A függvény legutolsó utasítása pedig az lenne, hogy ennek a lokális változónak a tatalma átkerülne a függvény nevére egy új értékadó utasítással, tehát pl. utkitt := bRet, ahol bRet egy boolean típusú (a függvény visszatérési típusa) lokális változó. Ezt persze nem kötelező így csinálni, működik enélkül is, csak úgy szerintem "szebb", ha a függvény ténylegesen EGYSZER kap értéket.

    > Variable identifier expected

    Ez pedig azért hibás a te esetedben mert "var" típusúak a függvényed paraméterei (mind a kettő), azaz CÍM szerinti paraméter átadást írtál elő, címe pedig NINCS a híváskor átadott második paraméterednek (starty-magassag*szorzo), csak értéke. A startx oké (mert a változóknak van címe), a starty-magassag*szorzo pedig nem oké. Ha leszeded a "var"-okat a függvény definíciód paramétereiről (amúgy jelen esetben nincs is rá szükség, úgy látom), akkor jó lesz.
    A "var" kulcsszót a paramétereknél csak indokolt esetben célszerű használni, vigyázni kell velük.

  • vz12

    tag

    válasz mekker #2009 üzenetére

    Szívesen, nincs mit.

    D5-ben nem volt még ilyen MainFormOnTaskbar property, úgy látom hogy ez a D2007-ben jelent meg.
    Az Application.Handle problémára egy Lazarus oldalon ilyen FindWindow megoldást adtak, gondolom hogy valami ilyesmit csináltál te is.

    A lényeg, hogy összejött a megoldás. ;)

  • vz12

    tag

    válasz mekker #2007 üzenetére

    Nekem is volt ilyen problémám régebben, előkerestem Neked a kódomból az én megoldásomat.
    Sosem dolgoztam Lazarussal, ez konkrétan Delphi5, és tökéletesen működik:

    SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW); // remove button from taskbar

    Ez valami Win API hívás, gondolom hogy menni fog Lazarusban is.
    Nem hiszem hogy magamtól találtam ki, most az előbb Google barátommal pl. ilyen megoldást találtam elég gyorsan, ami nagyon hasonlít az én kódomra.

    Remélem segítettem. :)

  • vz12

    tag

    válasz labuwx #1747 üzenetére

    Pl.
    canvas.Pen.color:=clRed;
    canvas.Brush.color:=clBlue;
    canvas.Ellipse(5,5,100,100);

    Ez rajzolni fog egy Piros határvonalú, belül Kék "korongot". RGB is használható.
    A vonal (Pen) és kitöltő (Brush) színeket mindig a rajzoló tevékenység ELŐTT kell beállítani, egy adott canvas-on csak 1 Pen és 1 Brush van, ezt a rajzoló utasítások közösen használják. Tehát pl. most egy vonal(50,50,80,80) utasítás Piros vonalat húzna, mert a Pen színe arra lett állítva, itt ugye nincs kitöltés tehát a Brush érdektelen. Szerintem olvasgasd a Help-et, a Delphi-nek elég jó van.

  • vz12

    tag

    válasz labuwx #1744 üzenetére

    Ez érdekes, ilyet én a D3-ban és D5-ben nem tapasztaltam. Ott simán engedte a vonalat túlhúzni a képen, persze a kívül eső részek nem látszottak. Kellett is ez a lehetőség mert pl. a vonal(0,488,488,488); nem húzná végig a vonalat, a (0,488) még rendben van, de a (488,488) kimaradna, a vonal 1 pixellel hamarabb érne véget, ezért a vonal(0,488,489,488); parancsot kellene alkalmazni a teljes vonal kirajzolásához, ez ugye elvileg 1 pixellel kilógna, de az nem látszik, viszont a (488,488) is jó lenne.

    Ilyen új Delphi-vel nincs tapasztalatom, de hátha másnak van. A helyedben addig is bátran kísérletezgetnék, gyűjteném a tapasztalatokat, kis kreativitással gyorsan rá lehet jönni sok mindenre és lehet fejlődni önállóan.

    Egy észrevétel: A "vonal" eljárást én nem a "RajzClick" eljárás belső eljárásaként definiálnám.

  • vz12

    tag

    válasz labuwx #1741 üzenetére

    Canvas.Line tényleg nincs.

    Canvas.MoveTo(x1,y1) odateszi (x1,y1)-ba a kezdőpontot.
    Canvas.LineTo(x2,y2) innen húz egy vonalat (x2,y2)-be előzetesen beállított stílussal (szín, vonalvastagság, stb.), ezután a kezdőpont már itt lesz, a következő LineTo már innen fog indulni ha el nem viszed innen. Szerintem érdemes saját Line(x1,y1,x2,y2) eljárást írni a fenti két eljárás felhasználásával, esetleg a színt és vonalvastagságot is érdemes betenni a paraméterekbe majd felhasználni, úgy "szebb", általánosabb eljárást kapsz.
    Egyébként egy MxN-es canvas koordinátái (0,0) és (M-1,N-1) között vannak, és a LineTo-nak tapasztalataim szerint (Delphi 5.0-ig) van egy olyan tulajdonsága hogy a VÉGpont utolsó pixelét nem szereti kitenni, lespórolja.

    A "canvas" tulajdonságait és eljárásait kell nézegetni a help-ben, van téglalap és ellipszis (kör) rajzolási lehetőség is, stb.

    Szerk.: Úgy látom hogy beelőztek, de mindegy. ;)

  • vz12

    tag

    válasz Yodafon #1727 üzenetére

    Örülök hogy sikerült megoldani, végülis rájöttél hogy hol a hiba. :)
    Nekem csak ez a rengeteg egyedi értékadó utasítás "bántja" a szememet, ciklusban szebb volna, de persze így is működik ... ;)

    Sudokut már én is csináltam Delphi-ben de én más úton jártam, semmi szükségem nem volt gridre.

  • vz12

    tag

    válasz Yodafon #1723 üzenetére

    Azt hiszem hogy egy kis hibát vétettem, ezt korrigálom:

    mezo[1].OnSelectCell:=Sajat_SelectCell; // paraméterek NÉLKÜL
    mezo[2].OnSelectCell:=Sajat_SelectCell; // paraméterek NÉLKÜL

    Helyesen tehát "OnSelectCell" kell ide ahogy Fire példáján is látszik, ezt tévesztettem el. Ha az értékadás jobb oldalaira azonos eljárás nevet írsz be akkor szerintem megvalósul amit szeretnél, tehát közös OnSelectCell eljárása lesz minden példánynak.

    Egyébként ez is belerakható ám a ciklusba, így lesz biztosítva a legegyszerűbben a közös OnSelectCell, tehát:
    mezo[i].OnSelectCell:=Sajat_SelectCell; // paraméterek NÉLKÜL

    A többi rész viszont változatlan, tehát a Sajat_SelectCell eljárást szigorúan a definiálandó eljárás paraméterlistájával (OnSelectCell) deklarálni és definiálni (kifejteni) kell.

    procedure TForm1.Sajat_SelectCell(Sender: TObject; ACol,
    ARow: Integer; var CanSelect: Boolean);

    Meghíváskor át kell adni a paramétereket is!
    Pl. mezo[1].OnSelectCell(Sender,1,1,bValtozo);
    Figyelj rá hogy a 4. paraméternek logikai változónak kell lennie a "VAR" miatt!
    Ez át fog irányítódni a form Sajat_SelectCell eljárásába és továbbadja a paramétereket is. Viszont a Sajat_SelectCell-t meg kell írni !!! Tehát le kell reagálni a cella kiválasztódás eseményét, ha nem írsz bele semmit akkor ilyenkor nem fog történni semmi. Legalábbis úgy gondolom, mert ezt sem próbáltam ki. :)

  • vz12

    tag

    válasz Yodafon #1720 üzenetére

    Próbáld meg valahogy így:

    mezo[1].SelectCell:=Sajat_SelectCell; // paraméterek NÉLKÜL

    mezo[2].SelectCell:=Sajat_SelectCell; // paraméterek NÉLKÜL

    Valamint szigorúan "eredeti" paraméterlistával:

    procedure TForm1.Sajat_SelectCell(Sender: TObject; ACol,
    ARow: Integer; var CanSelect: Boolean);

    Ezt a deklarációs résszel összhangban a kódba is bele kell tenni (természetesen ott kifejtve).

    Hozzáteszem hogy nem próbáltam ki, ezen a gépen nincs Delphi sem, de elvileg így kell és ez gyakorlatilag semmiben nem különbözik a "normál" esettől, annak jobb könyvekben benne kell lennie.

    Ha már ilyen előrelátó módon tömbbe szervezted az objektumokat akkor azok közös adatait (itt majdnem mind az) én a ciklusban inicializáltam volna a "parent"-hez hasonlóan, tehát pl. mezo[i].Top:=20;

  • vz12

    tag

    válasz Prego #1711 üzenetére

    Az eljárás hívása nem változik.
    Az eljárás fejbe a paraméterlistába beletettem egy "VAR" szócskát mert az most szerintem kell. :) Módosítani kell a deklarációban is + a kódban is.

    Én eddig egyszerre 1 komponenst tudtam "lehúzni a formra", de annak nincs semmi akadálya hogy ha már lent van akkor CTRL-C + CTRL-V "módszerrel" szaporítsd őket, így lehet (újrakijelölésekkel) 1-ből 2, 2-ből 4-, 4-ből 8, stb. példány. A végén meg annyi amennyi még hiányzik. :) Kicsit biztosan egymásra rakja őket, utána el kell húzni a helyére.

  • vz12

    tag

    válasz Prego #1708 üzenetére

    Ha még él a probléma akkor próbáld meg így:

    procedure TForm2.EmptyArray (var T: array of TImage);

Új hozzászólás Aktív témák

Hirdetés