Auttakaa tämän windowsin kahvan kanssa

Aloittelija5

BOOL WriteFile(
HANDLE hFile, // handle to file to write to
LPCVOID lpBuffer, // pointer to data to write to file
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
LPOVERLAPPED lpOverlapped // pointer to structure for overlapped I/O
);

ELI miten tämä pitäisi määritellä Delphissä? kokoajan kääntäjä ilmoittaa virhettä, olen aloittelija näiden windowsin kahvojen kanssa, jos joku voisi auttaa suomenkielellä tämän olisin hyvin kiitollinen.
Tarkoituksena olisi saada kirjoittaan sarjaporttiin, kuin lukukin ReadFile:llä.
Käytössä vanha delphi 7.

6

212

    Vastaukset 6

    Anonyymi (Kirjaudu / Rekisteröidy)
    5000
    • 20+6

      Eikö se ole jo määritelty valmiiksi? Ainakin 5-versiossa on.

    • Delphiguru

      "Tarkoituksena olisi saada kirjoittaan sarjaporttiin"

      Jos siis haluat omasta Delphillä tehtävästä ohjelmastasi käsin käyttää sarjaporttia (koskee yhtälailla oikeita COM1 -tyyppisiä laitesarjaportteja kuin myös virtuaalisia esim. COM11 -sarjaportteja, eli USB -laite, joka ohjelmiston näkökulmasta toimii kuten perinteinen sarjaportti), niin suosittelen, ettet tuhlaa aikaasi API -kutsujen kanssa, vaan imuroit ja asennat koneellesi Synapse -kokoelmaan kuuluvan SynaSer -paketin.

      SynaSer on ite kokeilemastani luotettavasti toimiva Delphi -unit sarjaporttien käsittelyyn.

      SynaSer:in löydät täältä:

      http://www.ararat.cz/synapse

      kohdasta "News":

      2007-12-21 New SynaSer release 16! News are:
      Support for non-LIBC Freepascal Unix based targets.

      Kun ensin luot komponentin ja määrittelet sen parametrit:

      var
      FCommPort : TBlockSerial;

      // Luo ja konfiguroi sarjaportti:

      FCommPort := TBlockSerial.Create;

      FCommPort.Connect(FCommPortName);

      if NOT FCommPort.InstanceActive
      then Exit;

      FCommPort.config(115200,8,'N',0,false,true); // HW Handshake

      // Portin SULKEMINEN:

      FCommPort.CloseSocket;


      Datan lähetys sarjaporttiin:

      var
      S : AnsiString;

      // HUOM: Delphi 2009 ja uudemmat: Tämän on OLTAVA AnsiString, EI String.
      // Vanhemmissa Delphi -versioissa kuin Delphi 2009, String = AnsiString.

      begin
      S := 'ATDT080002202;' #13; // komento, joka soittaa äänipuhelun siirrettyjen numeroiden tiedotuspalveluun, #13 = CR = Carriage return

      if S '' then FCommPort.SendBuffer( @S[1], Length(S) );

      end;

      Sarjaportin lukemiseen suosittelen TBlockSerial -luokan metodeja:

      RecvBuffer

      RecvBufferEx

      riippuen siitä, haluatko jäädä odottamaan, kunnes haluttu määrä dataa on luettavissa vai haluatko määritellä maksimiodotusajan, jonka jälkeen funktio palaa kutsujalleen siinäkin tapauksessa, että luettujen tavujen määrä on pyydettyä pienempi.

      • kysyjää

        Miten tuo datan luku SynaSer:llä sujuu. Millaiseen muuttujaan data tallennetaan- Voisi saada vastaavan esimerkin


      • Delphiguru
        kysyjää kirjoitti:

        Miten tuo datan luku SynaSer:llä sujuu. Millaiseen muuttujaan data tallennetaan- Voisi saada vastaavan esimerkin

        ohjeita SYNASER käytöstä täällä:

        http://synapse.ararat.cz/doc/help/synaser.html

        ja lisää:

        http://synapse.ararat.cz/doc/help/synaser.TBlockSerial.html

        function RecvBuffer(buffer: pointer; length: integer): integer; virtual;

        function RecvBufferEx(buffer: pointer; length: integer; timeout: integer): integer; virtual;

        siis....

        ESIMERKIKSI näin:

        const
        MaxLength = 1024;

        MaxDelay_ms = 500; // 500 ms = ½ sekuntia.

        var
        S : AnsiString;

        L : Integer;

        begin

        //
        SetLength(S, MaxLength);

        //

        L := RecvBuffer(PAnsiChar(S), MaxLength);

        if L < 0 then L := 0;

        SetLength(S, L);

        // Muuttujassa S on nyt 1024 tavua = 1024 merkkiä sarjaportista luettua dataa.

        JOS luetun datan pituus EI ole etukäteen tiedossa, fiksumpi voi silloin olla muuten samoin, mutta RecvBuffer korvataan RecvBufferEx, siis näin:


        L := RecvBufferEx(PAnsiChar(S), MaxLength, MaxDelay_ms);

        (*
        Toimii muuten samoin, mutta jos ½ sekunnin sisällä on dataa luettu vähemmän kuin 1024 tavua, funktio palaa silloinkin kutsujalleen, ja muuttuja L sisältää luettujen tavujen määrän.
        *)

        end;

        HUOM:
        Käytännössä on yleensä parempi käyttää RecvBufferEx -funktiota, sillä pelkkä RecvBuffer on käyttökelpoinen vain, jos tiedetään etukäteen luettavien tavujen tarkka määrä. RecvBuffer siis odottaa loputtomiin, kunnes annettu tavumäärä on kokonaan luettu, kun taas RecvBufferEx palaa joka tapauksessa kutsujalleen, kun viiveaika (millisekunteina) on kulunut, vaikka dataa olisikin luettu vähemmän kuin annettu maksimimäärä.

        JOS teet sovelluksestasi 1-säikeisen, niin suosittelen TTimer -komponentin käyttöä, ja RecvBufferEx -funktion kutsumista OnTimer -tapahtumakäsittelijästä.

        TOINEN vaihtohto on käyttää säikeitä ( New / Thread ) ja tehdä sarjaportin lukeminen omassa erillisessä säikeessään, jotta käyttöliittymä ei jumitu sillä aikaa kun odotellaan dataa saapuvaksi sarjaporttiin.

        Pääsäikeestä kutsuttuna tuo L := RecvBufferEx(PAnsiChar(S), MaxLength, MaxDelay_ms); missä MaxDelay_ms = 500, odottaa aina ½ sekuntia kutsukertaa kohden, paitsi jos kutsuttaessa funktiota voidaan suoraan sisäisestä puskurimuistista lukea koko haluttu datamäärä täyteen, jolloin ei odotella.

        JOS siis teet 1 -säikeisen ohjelman, voit hyvin pudottaa tuon MaxDelay_ms = 50 jolloin odotusaika on enää 1/20 s , mikä ei niin häiritsevästi jumita käyttöliittymää.

        Toki vielä...

        if NOT FCommPort.InstanceActive
        then Exit;

        tuo kannattaa laittaa niihin proseduureihin/funktioihin, joissa kutsut muita sarjaportin funktioita kuten RecvBufferEx ja/tai SendBuffer ENNEN ko. funktiokutsuja.

        Tämä siksi, että RecvBufferEx ja/tai SendBuffer -funktion kutsuminen tilanteessa, jossa sarjaporttia ei ole avattu (tai avaaminen jostain syystä epäonnistui) voi nostaa poikkeuksen.

        FIKSUA ohjelmointia, jos käytät TTimer -komponenttia, on vielä esim. tämä:
        (OnTimer -käsittelijässä):

        var
        ErrorCount : Integer; // globaali muuttuja tai formin kenttä, EI paikallinen muuttuja !!!

        try

        // Koodia, joka lukee ja/tai kirjoittaa sarjaporttia


        except

        //
        ON E:Exception do begin

        //

        inc(ErrorCount);

        lblError.Visible := True;

        lblError.Caption := IntToStr(ErrorCount) '. poikkeus: ' E.Message;

        end;

        end;

        Tuon ansiosta tilanne EI riistäydy hallinnasta, JOS OnTimer -käsittelijässä tai siitä kutsutussa aliohjelmassa aiheutuu poikkeus. Muussa tapauksessa tulee Delphin omia poikkeusilmoitus -dialogeja nopeammin kuin niitä ehtii sulkea,

        JOS näin käy, Delphin Ctrl-F2 on ystäväsi (tai Windows tehtävänhallinnan lopeta ohjelma, JOS Delphi ei ole käynnissä, vaan käynnistit oman ohjelmasi suoraan Delphin ulkopuolelta).


      • monisäikeinen,
        Delphiguru kirjoitti:

        ohjeita SYNASER käytöstä täällä:

        http://synapse.ararat.cz/doc/help/synaser.html

        ja lisää:

        http://synapse.ararat.cz/doc/help/synaser.TBlockSerial.html

        function RecvBuffer(buffer: pointer; length: integer): integer; virtual;

        function RecvBufferEx(buffer: pointer; length: integer; timeout: integer): integer; virtual;

        siis....

        ESIMERKIKSI näin:

        const
        MaxLength = 1024;

        MaxDelay_ms = 500; // 500 ms = ½ sekuntia.

        var
        S : AnsiString;

        L : Integer;

        begin

        //
        SetLength(S, MaxLength);

        //

        L := RecvBuffer(PAnsiChar(S), MaxLength);

        if L < 0 then L := 0;

        SetLength(S, L);

        // Muuttujassa S on nyt 1024 tavua = 1024 merkkiä sarjaportista luettua dataa.

        JOS luetun datan pituus EI ole etukäteen tiedossa, fiksumpi voi silloin olla muuten samoin, mutta RecvBuffer korvataan RecvBufferEx, siis näin:


        L := RecvBufferEx(PAnsiChar(S), MaxLength, MaxDelay_ms);

        (*
        Toimii muuten samoin, mutta jos ½ sekunnin sisällä on dataa luettu vähemmän kuin 1024 tavua, funktio palaa silloinkin kutsujalleen, ja muuttuja L sisältää luettujen tavujen määrän.
        *)

        end;

        HUOM:
        Käytännössä on yleensä parempi käyttää RecvBufferEx -funktiota, sillä pelkkä RecvBuffer on käyttökelpoinen vain, jos tiedetään etukäteen luettavien tavujen tarkka määrä. RecvBuffer siis odottaa loputtomiin, kunnes annettu tavumäärä on kokonaan luettu, kun taas RecvBufferEx palaa joka tapauksessa kutsujalleen, kun viiveaika (millisekunteina) on kulunut, vaikka dataa olisikin luettu vähemmän kuin annettu maksimimäärä.

        JOS teet sovelluksestasi 1-säikeisen, niin suosittelen TTimer -komponentin käyttöä, ja RecvBufferEx -funktion kutsumista OnTimer -tapahtumakäsittelijästä.

        TOINEN vaihtohto on käyttää säikeitä ( New / Thread ) ja tehdä sarjaportin lukeminen omassa erillisessä säikeessään, jotta käyttöliittymä ei jumitu sillä aikaa kun odotellaan dataa saapuvaksi sarjaporttiin.

        Pääsäikeestä kutsuttuna tuo L := RecvBufferEx(PAnsiChar(S), MaxLength, MaxDelay_ms); missä MaxDelay_ms = 500, odottaa aina ½ sekuntia kutsukertaa kohden, paitsi jos kutsuttaessa funktiota voidaan suoraan sisäisestä puskurimuistista lukea koko haluttu datamäärä täyteen, jolloin ei odotella.

        JOS siis teet 1 -säikeisen ohjelman, voit hyvin pudottaa tuon MaxDelay_ms = 50 jolloin odotusaika on enää 1/20 s , mikä ei niin häiritsevästi jumita käyttöliittymää.

        Toki vielä...

        if NOT FCommPort.InstanceActive
        then Exit;

        tuo kannattaa laittaa niihin proseduureihin/funktioihin, joissa kutsut muita sarjaportin funktioita kuten RecvBufferEx ja/tai SendBuffer ENNEN ko. funktiokutsuja.

        Tämä siksi, että RecvBufferEx ja/tai SendBuffer -funktion kutsuminen tilanteessa, jossa sarjaporttia ei ole avattu (tai avaaminen jostain syystä epäonnistui) voi nostaa poikkeuksen.

        FIKSUA ohjelmointia, jos käytät TTimer -komponenttia, on vielä esim. tämä:
        (OnTimer -käsittelijässä):

        var
        ErrorCount : Integer; // globaali muuttuja tai formin kenttä, EI paikallinen muuttuja !!!

        try

        // Koodia, joka lukee ja/tai kirjoittaa sarjaporttia


        except

        //
        ON E:Exception do begin

        //

        inc(ErrorCount);

        lblError.Visible := True;

        lblError.Caption := IntToStr(ErrorCount) '. poikkeus: ' E.Message;

        end;

        end;

        Tuon ansiosta tilanne EI riistäydy hallinnasta, JOS OnTimer -käsittelijässä tai siitä kutsutussa aliohjelmassa aiheutuu poikkeus. Muussa tapauksessa tulee Delphin omia poikkeusilmoitus -dialogeja nopeammin kuin niitä ehtii sulkea,

        JOS näin käy, Delphin Ctrl-F2 on ystäväsi (tai Windows tehtävänhallinnan lopeta ohjelma, JOS Delphi ei ole käynnissä, vaan käynnistit oman ohjelmasi suoraan Delphin ulkopuolelta).

        Tein tälläisen version (perustuu ylläolevaan )

        function TForm1.vastaanota:string;
        var
        S : AnsiString;
        L : Integer;
        begin
        SetLength(S, MaxLength);
        L := FCommPort.RecvBufferEx(PAnsiChar(S), MaxLength, MaxDelay_ms);
        if L < 0 then L := 0;
        SetLength(S, L);
        result := s;
        end;



        Millainen koodi tulisi jos tuo vastaanotto olisi omassa säikeessä. Ei ole aikaisempaa kokemusta monisäikeisestä ohjelmpoinnista.


    • 5dpo

    Ketjusta on poistettu 0 sääntöjenvastaista viestiä.

    Luetuimmat keskustelut

    1. Olen nainen pahoillani, että tykkään sinusta niin paljon, että

      Haluaisin panna sua. Tuntuu vaan siltä, että olet sen suhteen ihan haluton. Ei minulle riitä pelkkä ystävyyssuhde.
      Ikävä
      64
      1051
    2. Mieti oikeasti

      Ollaan lähes tuntemattomia, mutta samalla on tämä erityinen vuosien tilanne takana, joka on ollut monella tapaa väärin.
      Ikävä
      30
      687
    3. Taasko sä vedit

      Suojamoodin päälle? Miehelle
      Ikävä
      90
      685
    4. Puukotus Kajaanissa

      Kuka puukotti ja ketä? https://yle.fi/a/74-20247765 Vähemmän yllättäen päihteet mainittu
      Kajaani
      26
      678
    5. Liikenneonnettumuus

      Linkkari ja ruotsibiili törmäsivät linkku oli redun opetusajossa
      Ylitornio
      9
      661
    6. Tiedoksi yhdelle naiselle

      että mies lähestyy kaikin tavoin jos on kiinnostunut! 🙋🏻‍♂️
      Ikävä
      46
      648
    7. kene ajoi "kolarin"?

      "Punkaharjulla Luston ja Tuppuranmäen välillä sattui tiistaina aamupäivällä liikenneonnettomuus. Poliisin mukaan Savonl
      Savonlinna
      14
      635
    8. Pahin tapa satuttaa toista

      On jättää toinen vaille mitään vastausta. Erityisen kipeää se tekee sillon jos toinen ghostaa.
      Ikävä
      68
      629
    9. Miten uskallan sua nähdä

      Kun vaikutat suuttuneelta :(
      Ikävä
      42
      560
    10. Alkaa jotenkin nyt kuvio hahmottuu täällä

      Sellainen vaikutelma tästä alkaa tulla, että täällä on joku pieni porukka, joka tuntee toisensa tai ainakin pelaa samaan
      Ikävä
      82
      558
    11. Minulla on joskus ikävä sinua ja ajattelen sinua joskus.. edelleen

      Olin joskus niin rakastunut sinuun. Olin onnellinen, että kohdattiin ja kun vain tiesin sinun olevan olemassa. Täytit aj
      Ikävä
      22
      558
    12. 61
      549
    13. Mitä söpö

      Mies mietit?
      Ikävä
      62
      546
    14. Minä kyllä odotan nainen

      että sinun kanssa voisin jutella asioista ihan oikeasti.
      Ikävä
      43
      534
    15. Jos kaivattusi on

      Varattu niin miksi et antaisi asian olla hänen suhteen. Miksi ylipäätään vielä jatkat?
      Ikävä
      46
      530
    16. Hyvä on sitten, jos et sitä s*ksiä halua kanssani.

      Rakastetaan vaan toisiamme, voin käydä muualla tyydyttämässä fyysisenpuolen tarpeet. Puhumalla tämäkin olisi selvinnyt.
      Ikävä
      134
      508
    17. Kylän tielle remonttia?

      Mitäköhän kylän tielle ruvetaan tekemään ku laitettu tuommoset töpsät muutamien suojateitten kohille?
      Hyrynsalmi
      13
      492
    18. Miten vuosien jälkeenkin tunteet voivat olla niin voimakkaat?

      Että pelkkä ajatus sinusta täyttää silmät kyynelistä.
      Ikävä
      27
      437
    19. Nainen, tässä olen kahden vaiheilla

      Toinen pitäisi valita ja kummassakin on hyvät ja huonot puolensa. Toinen olisi sellainen pysyvä mutta työläs. Toinen taa
      Ikävä
      46
      433
    20. Suloinen ja herkkä

      Toiset huomioiva, räväkkä, yllättävä. Ei sellaisesta voi olla pitämättä.
      Rakkaus ja rakastaminen
      29
      433
    Aihe