Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[Delphi] CreateForm-mysterie

Pagina: 1
Acties:
  • 223 views sinds 30-01-2008
  • Reageer

  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 28-11 12:23

Bergen

Spellingscontroleur

Topicstarter
Ik ben even een screensaver aan het maken (voor dit topic, voor wie het wil weten) en loop tegen iets heel vreemds aan.

In de project-unit moet ik uiteraard even kijken of er wordt aangeroepen met /c of met /s. De unit ziet er zo uit, let vooral op de 2 if's, want daar gaat het om:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
program Greysaver;

uses
  Forms,
  ScreensaverUnit in 'ScreensaverUnit.pas' {ScreensaverForm},
  ConfigurationUnit in 'ConfigurationUnit.pas' {ConfigurationForm};

{$D SCRNSAVE Greysaver}
{$R *.res}

var
  param: string;

begin
  Application.Initialize;
  if ParamCount = 1 then
  begin
    param := Copy(ParamStr(1), 1, 2);
    if param = '/s' then
      Application.CreateForm(TScreensaverForm, ScreensaverForm);
    if param = '/c' then
      Application.CreateForm(TConfigurationForm, ConfigurationForm);
  end;
  Application.Run;
end.
Voor wie vraagtekens zet bij Copy(ParamStr(1), 1, 2): ik las ooit ergens dat Windows soms meer meestuurt dan /s of /c. Daarom kun je het beste alleen de eerste 2 karakters pakken. Anyway, daar gaat het nu even niet om.

Bovenstaande code werkt prima. Je zou alleen zeggen dat een if-else mooier is en daar komt het vreemde om de hoek kijken. Zodra ik achter de eerste CreateForm-regel de puntkomma weghaal, wordt de groene 'play'-knop van Delphi (om je app te runnen) ineens grayed-out, dus je kunt de applicatie niet meer starten. Je zou zeggen dat er ergens een error zit. Ook als ik de code verder in orde maak, dus de else toevoeg enzo, blijft de code niet runnable. Als ik Project > Syntax Check doe levert dat geen meldingen op. Dan ziet de code er dus zo uit:
Delphi:
1
2
3
4
    if param = '/s' then
      Application.CreateForm(TScreensaverForm, ScreensaverForm)
    else
      Application.CreateForm(TConfigurationForm, ConfigurationForm);

of zo:
Delphi:
1
2
3
4
    if param = '/s' then
      Application.CreateForm(TScreensaverForm, ScreensaverForm)
    else if param = '/c' then
      Application.CreateForm(TConfigurationForm, ConfigurationForm);
Als ik er dit van maak werkt het weer wel: (de CreateForm tussen begin en end)
Delphi:
1
2
3
4
5
    if param = '/s' then
    begin
      Application.CreateForm(TScreensaverForm, ScreensaverForm);
    end else if param = '/c' then
      Application.CreateForm(TConfigurationForm, ConfigurationForm);
Maar ook als in binnen die begin-end de puntkomma achter die regel weglaat wordt de playknop weer grijs, terwijl je normaal gesproken voor een end altijd de puntkomma mag weglaten.

Is dit een bug in Delphi of heeft dit een reden? :?

Ik gebruik Delphi 7, als dat ertoe doet. Delphi even sluiten en weer openen helpt niet.

[ Voor 30% gewijzigd door Bergen op 21-05-2005 03:07 ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Ik vermoed dat Delphi moeite heeft met het zien vertakking je binnengaat, en denkt dat je geen form aanmaakt of iets dergelijks. Waarom het dan wel werkt met begin en end erbij weet ik niet, het ziet er inderdaad uit als een bug, maar daar weten de hier rondstruinende Delphi-goeroes vast meer vanaf. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 28-11 12:23

Bergen

Spellingscontroleur

Topicstarter
Yep, het lijkt te maken te hebben met de available en auto-create forms, maar ik ben er nog niet helemaal uit. Het blijft vreemd waarom hij zo gevoelig is voor die puntkomma, vooral tussen dat begin-end ding.

[edit]
Als ik eerst alle formulieren op 'available' zet, dan de code verander in een van de bovenstaande niet-werkende vormen en ik dan de project-options probeer aan te roepen, zegt Delphi: "Error in module Greysaver: Call to Application.CreateForm is missing or incorrect." Dan moet ik de code weer werkend maken (door bijvoorbeeld begin en end eromheen te zetten), om weer bij de project-options te kunnen.

Wat bijvoorbeeld ook wel werkt is:
Delphi:
1
2
3
4
5
begin
  param := Copy(ParamStr(1), 1, 2);
  if param = '/s' then
    Application.CreateForm(TScreensaverForm, ScreensaverForm);
end;
Maar niet zonder die puntkomma. 8)7 Volgens mij is 't gewoon een bug.

Als iemand met de zooi wil stoeien kun je hier de boel downloaden.

[ Voor 106% gewijzigd door Bergen op 21-05-2005 03:46 ]


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 22:47

alienfruit

the alien you never expected

FYI Het werkt volgens mij wel goed in Delphi 2005 (Win32) :)
http://skrud.net/posts/34...n-in-delphi-is-not-a-bug/

[ Voor 38% gewijzigd door alienfruit op 21-05-2005 06:14 ]


  • Dala
  • Registratie: November 2000
  • Laatst online: 24-11 22:28
sinds begin van pascal is ';' een onderscheiding tussen twee commando's niet het einde van een commando (zoals bv in c)

Delphi:
1
2
3
4
5
6
{ wat bijvoorbeeld ook mag:}
if blaat then
begin
  Commando1;
  Commando2
end;

vroeger was dit zelfs een optimalisatie, want dan kreeg je een nop minder (zoiets was het).. in delphi(object pascal) en pascal is de ';' altijd bedoelt als scheiding tussen commando's.. en de end en else zijn opzichzelf ook al indicaties voor een scheiding.

[ Voor 5% gewijzigd door Dala op 21-05-2005 19:23 ]


  • Dala
  • Registratie: November 2000
  • Laatst online: 24-11 22:28
maar meteen eens gekeken..
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
program Greysaver;

uses
  Forms, SysUtils,
  ScreensaverUnit in 'ScreensaverUnit.pas' {ScreensaverForm},
  ConfigurationUnit in 'ConfigurationUnit.pas' {ConfigurationForm};

{$D SCRNSAVE Greysaver}
{$R *.res}

var
  param: string;

begin
  Application.Initialize;
  if ParamCount = 1 then
  begin
    param := LowerCase(Copy(ParamStr(1), 1, 2));
    if param = '/s' then
      Application.CreateForm(TScreensaverForm, ScreensaverForm)
    else if param = '/c' then
      Application.CreateForm(TConfigurationForm, ConfigurationForm)
    else
      Exit;
  end
  else
    Exit;
  Application.CreateForm(TConfigurationForm, ConfigurationForm);
  Application.Run;
end.


mijn delphi vond het niet leuk dat er soms geen createform plaatsvond..
nu lijkt het gewoon alsof.. maar eigenlijk komt altijd de exit eerst, zoiezo ook ff SysUtils toegevoegd en daarbij LowerCase over je param heenn dit werkt bij mij

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 15:10

Creepy

Tactical Espionage Splatterer

Oftewel: geen bug in Delphi ;) Die wil gewoon dat er een altijd een CreateForm wordt gedaan.

Als je een ; vergeet krijg je daar overigens netjes een echte error over, maar ik geloof niet dat dat verder iets te maken heeft gehad met het probleem :)

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 20-11 11:59

NMe

Quia Ego Sic Dico.

Creepy schreef op zaterdag 21 mei 2005 @ 20:34:
Oftewel: geen bug in Delphi ;) Die wil gewoon dat er een altijd een CreateForm wordt gedaan.
Of het een bug is of niet weet ik niet, maar onverwacht gedrag is het wel. Als je een vertakking hebt, met in beide takken een CreateForm, dan zou dat gewoon moeten werken. En ik vind het toch al op zijn minst vreemd dat het in een compound statement tussen begin en end wel werkt, maar gewoon zo als enkelvoudig commando niet. :X

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Verwijderd

Dala schreef op zaterdag 21 mei 2005 @ 19:42:
maar meteen eens gekeken..
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
program Greysaver;

uses
  Forms, SysUtils,
  ScreensaverUnit in 'ScreensaverUnit.pas' {ScreensaverForm},
  ConfigurationUnit in 'ConfigurationUnit.pas' {ConfigurationForm};

{$D SCRNSAVE Greysaver}
{$R *.res}

var
  param: string;

begin
  Application.Initialize;
  if ParamCount = 1 then
  begin
    param := LowerCase(Copy(ParamStr(1), 1, 2));
    if param = '/s' then
      Application.CreateForm(TScreensaverForm, ScreensaverForm)
    else if param = '/c' then
      Application.CreateForm(TConfigurationForm, ConfigurationForm)
    else
      Exit;
  end
  else
    Exit;
  Application.CreateForm(TConfigurationForm, ConfigurationForm);
  Application.Run;
end.
Nofi, maar wat een smerige code met die exits erin..

Delphi:
1
2
3
4
5
6
7
  Application.Initialize;
  if ParamCount>0 and StrLen(paramstr(1))>1 then
    case paramstr(1)[2] of
      's' : Application.CreateForm(TScreensaverForm, ScreensaverForm); 
      'c' : Application.CreateForm(TConfigurationForm, ConfigurationForm); 
    end;
  Application.Run;


Vind ik persoonlijk een stuk netter. En werkt ook nog :)..

[ Voor 27% gewijzigd door Verwijderd op 21-05-2005 22:13 ]


  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 28-11 12:23

Bergen

Spellingscontroleur

Topicstarter
Dala schreef op zaterdag 21 mei 2005 @ 19:42:
maar meteen eens gekeken..

[stuk code]

mijn delphi vond het niet leuk dat er soms geen createform plaatsvond..
nu lijkt het gewoon alsof.. maar eigenlijk komt altijd de exit eerst, zoiezo ook ff SysUtils toegevoegd en daarbij LowerCase over je param heenn dit werkt bij mij
In die vorm is jouw app uitvoerbaar? Welke versie van Delphi gebruik je? In dezelfde opzet, dus:
Delphi:
1
2
3
4
5
6
7
    param := Copy(ParamStr(1), 1, 2);
    if param = '/s' then
      Application.CreateForm(TScreensaverForm, ScreensaverForm)
    else if param = '/c' then
      Application.CreateForm(TConfigurationForm, ConfigurationForm)
    else
      Exit;
Is de run-knop weer grayed out bij mij. Als ik begin en end om de eerste regel zet (en een puntkomma achter die regel, dat moet beslist) is het pas weer uitvoerbaar, zo dus:
Delphi:
1
2
3
    begin
      Application.CreateForm(TScreensaverForm, ScreensaverForm);
    end else... (etc)
Dat is toch zo onlogisch als wat? De werking van de code verandert er toch helemaal niet door? Die lowercase is idd wel even een goed idee.

(Ik ondervind er verder geen last van hoor... Het is niet iets wat opgelost moet worden ofzo.)

[ Voor 6% gewijzigd door Bergen op 21-05-2005 22:06 ]


  • Dala
  • Registratie: November 2000
  • Laatst online: 24-11 22:28
ctrl-f9 doen.. en dan kun je exe zien in de dir ;)

edit:

stupid.. ja zou waarschijnlijk foutje zijn van ide praser... want hij compiled wel gewoon..

[ Voor 53% gewijzigd door Dala op 21-05-2005 22:53 ]


  • Dala
  • Registratie: November 2000
  • Laatst online: 24-11 22:28
Verwijderd schreef op zaterdag 21 mei 2005 @ 22:02:
[...]


Nofi, maar wat een smerige code met die exits erin..

Delphi:
1
2
3
4
5
6
7
  Application.Initialize;
  if ParamCount>0 and StrLen(paramstr(1))>1 then
    case paramstr(1)[2] of
      's' : Application.CreateForm(TScreensaverForm, ScreensaverForm); 
      'c' : Application.CreateForm(TConfigurationForm, ConfigurationForm); 
    end;
  Application.Run;


Vind ik persoonlijk een stuk netter. En werkt ook nog :)..
ging om het idee, tuurlijk schrijf ik zo geen echte projecten..
maar als we toch liggen zeuren.. hoe krijg je dit compiled terwijl StrLen gemaakt is voor PAnsiChars?
en hoe een if met 2 condities zonder '(' jes?
en waarom alles netjes met HoofdLetters schrijven behalve "ParamStr"?
en een "case LowerCase(ParamStr(1)[2]) of" is toch ook fijner, beetje flexibel moet je zijn :)

maarja, das gezeur ;)

[ Voor 18% gewijzigd door Dala op 21-05-2005 22:50 ]


Verwijderd

Die hele if heb ik er later op de bonnefooi tussen geedit.. laatste tijd meer met andere talen bezig, en dan wil je wel eens iets 'niet-delphi's' opschrijven.

Als je het echt netjes wilt doen, zou ik niet eens op die plek testen op die condities, maar gewoon een mainform maken die dat doet.

  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 28-11 12:23

Bergen

Spellingscontroleur

Topicstarter
Verwijderd schreef op zaterdag 21 mei 2005 @ 22:53:
Als je het echt netjes wilt doen, zou ik niet eens op die plek testen op die condities, maar gewoon een mainform maken die dat doet.
Dat is niet echt handig als je een screensaver maakt... Dan moet je Show gaan onderscheppen als je het configuratievenster wilt tonen, of het configuratievenster unhiden op 't MainForm ofzo. Dit is stukken handiger.

[ Voor 22% gewijzigd door Bergen op 21-05-2005 23:34 ]


Verwijderd

Bergen schreef op zaterdag 21 mei 2005 @ 23:32:Dat is niet echt handig als je een screensaver maakt... Dan moet je Show gaan onderscheppen als je het configuratievenster wilt tonen, of het configuratievenster unhiden op 't MainForm ofzo. Dit is stukken handiger.
Je show gaan onderscheppen? Een configuratievenster unhiden op 'n mainform?

Waar heb je het over?

  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 28-11 12:23

Bergen

Spellingscontroleur

Topicstarter
Heheheh ok, ik zal voortaan iets minder cryptisch zijn. :)

Stel je wilt de screensaver instellen. Dan moet je dus het configuratieform tonen. Jij zegt dat je de paramstrings liever controleert op het mainform. Als je bij het uitvoeren van het mainform er nog eens achterkomt dat je eigenlijk niet het mainform (dus de screensaver) wilt tonen, maar het configuratieform, zou je eigenlijk moeten voorkomen dat het mainform geshowed wordt. Dat bedoelde ik met de MainForm.Show onderscheppen.

Wat ook kan, is het configuratiescherm op het mainform zetten. Normaal gesproken zijn die controls dan zeg maar hidden, maar als je wilt configureren unhide je die controls en toon je het MainForm inclusief borders op normale afmetingen, ipv maximized enzo. Dat bedoelde ik met het configuratievenster unhiden.

Nouja, deze hele discussie is niet eens nodig als je gewoon ff die paar regels in de projectfile zet. Zowieso, zoek een willekeurige screensaver-in-delphi-tutorial en men zal je aanraden de boel te regelen in de projectfile.

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 22:47

alienfruit

the alien you never expected

Of je compileert het gewoon in Delphi 2005 Win32 compiler dan werkt het gewoon wel... beetje vaag. Onze grote vriend Steve is nu op vakantie dus die kan je niet vragen waarom het wel werkt in D2005 en niet in D7.

[ Voor 37% gewijzigd door alienfruit op 22-05-2005 00:53 ]


Verwijderd

Het compilen is het probleem niet. Je kunt het 'foute' programma in D7 wel via de commandline compilen. Als je Delphi op c: staat en het project heet 'project1':
code:
1
c:\progra~1\borland\delphi7\bin\dcc32.exe -Ic:\progra~1\borland\delphi7\lib -Rc:\progra~1\borland\delphi7\lib project1.dpr


Het is de IDE die de applicatie niet meer als uitvoerbaar ziet.

Lijkt mij wel degelijk een bug in de IDE.

[ Voor 84% gewijzigd door Verwijderd op 22-05-2005 01:30 ]


  • Dala
  • Registratie: November 2000
  • Laatst online: 24-11 22:28
ctrl-f9 doet het zelfde truukje zonder dat je dcc32.exe hoeft te gaan aanroepen ;) (zelf dan)

[ Voor 7% gewijzigd door Dala op 22-05-2005 01:26 ]


Verwijderd

Bergen schreef op zaterdag 21 mei 2005 @ 02:53:
Delphi:
1
2
3
...

{$D SCRNSAVE Greysaver}
Wordt deze naam ook daadwerkelijk door Windows gebruikt?
Ik heb dit nooit voor elkaar gekregen. (Is overigens al een tijdje geleden.)
Bergen schreef op zaterdag 21 mei 2005 @ 02:53:
Voor wie vraagtekens zet bij Copy(ParamStr(1), 1, 2): ik las ooit ergens dat Windows soms meer meestuurt dan /s of /c. Daarom kun je het beste alleen de eerste 2 karakters pakken.
Die extra waarde achter de preview-parameter is een Window-handle. Als je een preview laat zien dan moet je dit doen in het window dat je kunt benaderen met deze window-handle.
http://support.microsoft....?scid=kb%3Ben-us%3B182383

[ Voor 5% gewijzigd door Verwijderd op 22-05-2005 01:38 ]


Verwijderd

Ik heb trouwens nog wel een ietwat eenvoudiger workaround gevonden, behalve die case statements.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
program Project1;
uses
  Forms, Dialogs,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};
var
  strTest: string;
{$R *.res}

begin
  Application.Initialize;
  strTest := 't';
  With Application do
    if strTest='t' then
        CreateForm(TForm1, Form1)
      else
        CreateForm(TForm2, Form2);
  Application.Run;
end.


:)

//edit
Creepy schreef op zaterdag 21 mei 2005 @ 20:34:
Oftewel: geen bug in Delphi ;) Die wil gewoon dat er een altijd een CreateForm wordt gedaan.
Dit is niet waar ook zonder CreateForm kan en mag je de app compilen en runnen.

[ Voor 32% gewijzigd door Verwijderd op 22-05-2005 01:35 ]


  • Bergen
  • Registratie: Maart 2001
  • Laatst online: 28-11 12:23

Bergen

Spellingscontroleur

Topicstarter
Verwijderd schreef op zondag 22 mei 2005 @ 01:27:
[...]

Wordt deze naam ook daadwerkelijk door Windows gebruikt? Ik heb even gezocht naar 'scrnsave' op msdn en kan daar ook niets vinden.
Ik heb dit nooit voor elkaar gekregen. (Is overigens al een tijdje geleden.)
Vaag, dat wordt idd niet gebruikt nu je het zegt. Heb ook al zitten zoeken, een Duitse site had het over een dubbele punt achter SCRNSAVE, een Turkse site had de naam tussen < en >, maar 't helpt allemaal niet.
Die extra waarde achter de preview-parameter is een Window-handle. Als je een preview laat zien dan moet je dit doen in het window dat je kunt benaderen met deze window-handle.
http://support.microsoft....?scid=kb%3Ben-us%3B182383
Bedankt, dat vroeg ik me ook al af.
Verwijderd schreef op zondag 22 mei 2005 @ 01:31:
Ik heb trouwens nog wel een ietwat eenvoudiger workaround gevonden, behalve die case statements.

[code...]
Uiteindelijk heb ik 't zo gedaan:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  Application.Initialize;
  if (not AlreadyRunning) and (ParamCount > 0) then
  begin
    param := LowerCase(Copy(ParamStr(1), 1, 2));
    if param = '/s' then
    begin
      Application.CreateForm(TScreensaverForm, ScreensaverForm);
      Application.CreateForm(TConfigurationForm, ConfigurationForm);
    end
    else if param = '/c' then
    begin
      Application.CreateForm(TConfigurationForm, ConfigurationForm);
      Application.CreateForm(TScreensaverForm, ScreensaverForm);
    end;
  end;
  Application.Run;
Beide keren moeten beide forms worden aangemaakt. De ene keer omdat je de screensaver misschien wel ff wilt testen tijdens het configgen en de andere keer om de configuratie in te lezen, die is nodig voor de uitvoer. Het form wat het eerste wordt aangemaakt is automatisch het mainform.

De screensaver is trouwens gereleased, link naar 't topic staat in de ts.

[ Voor 13% gewijzigd door Bergen op 23-05-2005 02:37 ]

Pagina: 1