Problem mit DateTimePicker unter Windows 10 "Creators Update"

    Problem mit DateTimePicker unter Windows 10 "Creators Update"

    Hallo Zusammen,

    mit dem aktuellen Windows 10 Update "Creators Update" erschien das Problem, dass der DateTimePicker nicht mehr korrekt dargestellt wird.
    Nun kann man das Problem umgehen, indem man im Projekt die Einstellung macht "Runtime-Themes aktivieren".
    Da wir in unserem Softwarehaus mehrere Projekte in einem Update rausgeben habe ich ein Modul gebaut, welches alle Projekte mit der aktuellen
    Versionsnummer neu kompiliert und das Setup fertig macht. Das setzen der Versionsnummer passiert zum einen in der dproj-Datei und in der RES-Datei,
    welche automatisch eingebunden wird.
    Nun gibt es die BRCC32.exe, welche aus einer RC-Datei eine solche gewünschte RES-Datei erstellt.
    Die RC-Datei ist eine Textdatei, welche ich mit den Informationen für das Icon und den Versionsdaten füttere.
    Die erzeugte RES-Datei passte bisher wunderbar und alles war gut.
    Wenn in Delphi in den Optionen die Option "Runtime-Themes aktivieren" aktiviert wird, wird die RES-Datei überschrieben.
    In der neuen RES-Datei stehen alle Daten (auch das Icon und die Versionsnummer) sauber drin und zusätzlich gibt es
    (Wie ich mit dem Programm "XNRessourceEditor" rausfinden konnte) nun ein Block mit einer XML-Datei drin.
    In der Ansicht vom XNRessourceEditor steht dort "XP Theme Manifest" mit dem Unterpunkt "1" und dort wiederum
    als Unterpunkt "Deutsch (Deutschland)" mit den XML-Daten.
    Zum Testen habe ich die RC-Datei um die Zeile
    1 RT_MANIFEST "C:\TEST_RES\XP Theme Manifest.manifest"
    erweitert. Daraufhin erschien in XNRessourceEditor der Hauptpunkt "RT_MANIFEST" (also schon mit falschem Namen).
    Die Daten sind sonst aber scheinbar sauber drin.
    Wenn ich diese dann mit in der Projekt reinlade habe ich wieder die "falschen" DateTimePicker (er läd das
    Manifest nicht). Beim Umstellen der Option scheint die RES-Datei auch das einzige zu sein, was sich ändert.
    Die Projektdatei selbst scheint wohl nicht betroffen.

    Frage:
    Weiß jemand, wie ich eine RC-Datei erstellen kann, die ich mit hinzulade, so dass es den gleichen Effekt hat,
    als würde ich den Haken in den Optionen aktivieren. Leider fehlt mir auch das Verständnis zu RC-Dateien.
    Es würde warscheinlich schon helfen, wenn ich (oder jemand anderes) aus einer RES-Datei wieder die RC-Datei generieren könnte, dann
    müsste man den Unterschied ja erkennen können.
    Oder gibt es statt "RT_MANIFEST" eine Extra Art, sowie bei "VERSIONINFO", wo es Zusatzinformationen gibt?

    Vielen Dank für die Mühe. Ich hoffe ich konnte das Problem rüberbringen.

    Liebe Grüße
    Incocnito
    Verstehe ich dich richtig und du machst das normalerweise nicht so, sondern willst die Ressourcendatei jetzt nur verändern, damit du über die Kommandozeile compilieren kannst? Falls das so ist, kannst du den nächsten Absatz überspringen.

    Gibt es einen Grund, weshalb du die Projekt-Ressourcen-Datei manuell erstellen willst? Normalerweise ist das Vorgehen so:
    • Es gibt eine Ressourcendatei für dein Projekt. Die erstellt Delphi selbst anhand der Projektdatei so, dass sie Anwendungsbild, Versionsinformation und Manifest enthält. Du hast damit eigentlich nichts zu tun.
    • Wenn du zusätzliche Ressourcendateien einbinden willst, dann erstellst du RC-Dateien, die du mit brcc32 übersetzt und im Quellcode mit {$R ...} einbindest.

    Wie erreicht Delphi das Erzeugen der Ressourcendatei? Wenn ich ein Projekt compiliere und sich die Projektinformationen geändert haben, erstellt Delphi eine temporäre Datei <Projektname>.vrc. Diese Datei ist im Prinzip so wie eine .rc-Datei.
    Ein Beispiel dafür: Ich erstelle ein neues leeres Projekt in XE3 mit Manifest, verpasse dem ein Bild und eine Versionsnummer. Dann wird folgende Project1.vrc erstellt:

    Quellcode

    1. /* ----- VS_VERSION.dwFileFlags ----- */
    2. #define VS_FF_DEBUG 0x00000001L
    3. #define VS_FF_PRERELEASE 0x00000002L
    4. #define VS_FF_PATCHED 0x00000004L
    5. #define VS_FF_PRIVATEBUILD 0x00000008L
    6. #define VS_FF_INFOINFERRED 0x00000010L
    7. #define VS_FF_SPECIALBUILD 0x00000020L
    8. #define VS_FFI_FILEFLAGSMASK 0x0000003FL
    9. /* ----- VS_VERSION.dwFileOS ----- */
    10. #define VOS_UNKNOWN 0x00000000L
    11. #define VOS_DOS 0x00010000L
    12. #define VOS_OS216 0x00020000L
    13. #define VOS_OS232 0x00030000L
    14. #define VOS_NT 0x00040000L
    15. #define VOS_WINCE 0x00050000L
    16. #define VOS__BASE 0x00000000L
    17. #define VOS__WINDOWS16 0x00000001L
    18. #define VOS__PM16 0x00000002L
    19. #define VOS__PM32 0x00000003L
    20. #define VOS__WINDOWS32 0x00000004L
    21. #define VOS_DOS_WINDOWS16 0x00010001L
    22. #define VOS_DOS_WINDOWS32 0x00010004L
    23. #define VOS_OS216_PM16 0x00020002L
    24. #define VOS_OS232_PM32 0x00030003L
    25. #define VOS_NT_WINDOWS32 0x00040004L
    26. /* ----- VS_VERSION.dwFileType ----- */
    27. #define VFT_UNKNOWN 0x00000000L
    28. #define VFT_APP 0x00000001L
    29. #define VFT_DLL 0x00000002L
    30. #define VFT_DRV 0x00000003L
    31. #define VFT_FONT 0x00000004L
    32. #define VFT_VXD 0x00000005L
    33. #define VFT_STATIC_LIB 0x00000007L
    34. 1 VERSIONINFO
    35. FILEVERSION 1, 3, 2, 1
    36. PRODUCTVERSION 1, 0, 0, 0
    37. FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
    38. FILEOS VOS__WINDOWS32
    39. FILETYPE VFT_APP
    40. {
    41. BLOCK "StringFileInfo"
    42. {
    43. BLOCK "040904E4"
    44. {
    45. VALUE "FileVersion", "1.3.2.1\000\000"
    46. VALUE "ProductVersion", "1.0.0.0\000\000"
    47. }
    48. }
    49. BLOCK "VarFileInfo"
    50. {
    51. VALUE "Translation", 1033, 1252<NUL>
    52. }
    53. }
    54. MAINICON ICON "<ICON>"
    55. 1 24 "c:\\program files (x86)\\embarcadero\\rad studio\\10.0\\bin\\default_app.manifest"
    56. PLATFORMTARGETS RCDATA {1}

    Wobei hier <NUL> für #0 steht (ich hatte mich schon gewundert, wieso beim Reinkopieren in den Forumseditor immer an dieser Stelle aufgehört wird - ein ordentlicher Texteditor zeigt an, dass hier ein Steuerzeichen steht) und <ICON> für den absoluten Pfad der .ico-Datei.
    Diese Datei wird mit der Befehlszeile

    Quellcode

    1. c:\program files (x86)\embarcadero\rad studio\10.0\bin\cgrc.exe" -c65001 "<VRC-Datei>" -foProject1.res

    compiliert (es ist also nicht brcc32, sondern cgrc, der CodeGear-Ressourcencompiler - keine Ahnung, was genau der Unterschied ist, aber laut Copyright-Vermerk ist am brcc32 seit 1999 nichts mehr gemacht worden).

    Um das rauszufinden, habe ich Folgendes gemacht:
    • Mit ProcessMonitor alle Kindprozesse vom bds abgesucht und compiliert. Die erste Befehlszeile ist gleich der cgrc-Aufruf. (Der VRC-Dateiname ist übrigens nicht der Name des Projekts, sondern ein temporär erzeugter. Deswegen ist auch dem "Erzeugen"-Meldungsfenster nicht unbedingt zu vertrauen, in dem angeblich die Befehlszeile auch drinsteht.)
    • Die temporäre Datei wird sofort wieder gelöscht. Um reinzuschauen habe ich der cgrc.exe alle Berechtigungen entzogen, so dass die Anwendung nicht mehr ausgeführt werden kann. Delphi meldet den Fehler; nun wird die temporäre Datei tatsächlich nach <Projektname>.vrc umbenannt und verbleibt im Ordner der Projektdatei.
    • Beim nächsten Compilieren wird die Datei nicht nochmal neu erzeugt - falls sich nichts in den Optionen geändert hat - sondern cgrc mit der alten aufgerufen. Sobald man die nötigen Rechte wieder einräumt geht wieder alles.


    Auf diese Weise kannst du einmal für ein Projekt rausfinden, wie die Datei mit deiner Delphi-Version aussehen sollte und das dann als Schablone für alle anderen verwenden.
    Master of the EDH ;)
    Woohoo, das sieht gut aus! Dankeschön!

    Die Lösung ist nicht 42 (Kleiner Scherz bezüglich "Per Anhalter durch die Galaxis) sondern ... 24!
    Wenn ich statt "RC_MANIFEST" nur "24" rein schreibe, zeigt mir XNRessourceEditor den gleichen Inhalt für meine
    RES-Datei an, wie diejenige, welche durch Delphi selbst erstellt wird.

    Trotzdem vielleicht noch ein paar Anmerkungen/Fragen:

    projekter schrieb:


    ... Gibt es einen Grund, weshalb du die Projekt-Ressourcen-Datei manuell erstellen willst? ...

    Wir geben zu einem Update immer mehrere Programme raus, diese sollen alle aber die gleiche Versionsnummer haben, außerdem lässt sich über die RES-Datei das Icon auf den verschiedenen Programmierer-Rechnern viel besser pflegen. Wir haben immer viel Zeit für die Erstellung der Updates verwendet und unser Update-Programm spart hier an mehreren Stellen, alles was halt automatisiert wreden kann wandert nach und nach hier rein.

    projekter schrieb:


    ... Ich erstelle ein neues leeres Projekt in XE3 mit Manifest, verpasse dem ein Bild und eine Versionsnummer. ...

    Ich weiß leider nicht, wie man in Delphi XE ein Manifest einbindet.

    projekter schrieb:


    ...

    Quellcode

    1. ...
    2. MAINICON ICON "<ICON>"
    3. 1 24 "c:\\program files (x86)\\embarcadero\\rad studio\\10.0\\bin\\default_app.manifest"
    4. PLATFORMTARGETS RCDATA {1}

    ...

    Da ist sie ... die 24! :) ... Auch wenn es mich verwirrt, dass oft "#define RT_MANIFEST 24" zu finden ist, weshalb ich erst dachte, dass RT_MANIFEST schon 24 ist! 8|

    projekter schrieb:


    Diese Datei wird mit der Befehlszeile

    Quellcode

    1. c:\program files (x86)\embarcadero\rad studio\10.0\bin\cgrc.exe" -c65001 "<VRC-Datei>" -foProject1.res

    compiliert (es ist also nicht brcc32, sondern cgrc, der CodeGear-Ressourcencompiler - keine Ahnung, was genau der Unterschied ist, aber laut Copyright-Vermerk ist am brcc32 seit 1999 nichts mehr gemacht worden).

    Ich habe die CGRC.exe mal umbenannt, da ich nicht weiß wie man die Rechte entzieht, aber Delphi hat nicht gemeckert (vielleicht habe ich was übersehen).

    projekter schrieb:


    ...
    • Mit ProcessMonitor alle Kindprozesse vom bds abgesucht und compiliert. Die erste Befehlszeile ist gleich der cgrc-Aufruf. (Der VRC-Dateiname ist übrigens nicht der Name des Projekts, sondern ein temporär erzeugter. Deswegen ist auch dem "Erzeugen"-Meldungsfenster nicht unbedingt zu vertrauen, in dem angeblich die Befehlszeile auch drinsteht.)

    Ich habe das mit ProcMon von Sysinternals versucht, habe aber (wenn ich die beiden Logfile vergleiche) keinen Unterschied beim Erzeugen feststellen können. War ein ganz schönes Gefummel die restlichen Programme aus dem Protokoll zu entfernen ... Ich mag das Program gar nicht schließen mit den ganzen schönen Filtern! ;)

    projekter schrieb:


    ...
    Auf diese Weise kannst du einmal für ein Projekt rausfinden, wie die Datei mit deiner Delphi-Version aussehen sollte und das dann als Schablone für alle anderen verwenden.

    Das hat wie gesagt leider nicht so gut funktioniert, aber letztlich sind die erzeugten EXEen jetzt mit dem "alten"? DateTimePicker und laufen somit wieder!

    Also nochmals: Ich danke vielmals für die detailierte Info!

    Liebe Grüße
    Incocnito

    Incocnito schrieb:

    Wir geben zu einem Update immer mehrere Programme raus, diese sollen alle aber die gleiche Versionsnummer haben, außerdem lässt sich über die RES-Datei das Icon auf den verschiedenen Programmierer-Rechnern viel besser pflegen.

    Ok, das macht natürlich Sinn. Es ist etwas blöd: Die Versionsinformationen werden zwar in der .dproj gespeichert, aber damit sie im Programm landen, muss Delphi dies natürlich in eine Ressourcendatei konvertieren. Dummerweise macht das die IDE anscheinend intern, ich habe zumindest keinen externen Programmaufruf gefunden, der dafür zuständig ist. D.h., wenn du nicht über die IDE compilierst gibt es keine Möglichkeit, automatisch aus der .dproj eine .rc zu erzeugen - das wäre das Praktischste. Ich kann dir also leider keine angenehmere Alternative anbieten.

    Incocnito schrieb:

    Ich weiß leider nicht, wie man in Delphi XE ein Manifest einbindet.

    Ich gehe mal davon aus, dass das unter XE schon genauso war wie unter XE3: Projektoptionen > Anwendung > Laufzeit-Themes aktivieren. Das bindet das Standardmanifest ein. Ist bei mir auch standardmäßig schon vorausgewählt.

    Incocnito schrieb:

    Auch wenn es mich verwirrt, dass oft "#define RT_MANIFEST 24" zu finden ist, weshalb ich erst dachte, dass RT_MANIFEST schon 24 ist!

    Ich habe mal etwas gesucht und hauptsächlich Beiträge von himitsu in der DP gefunden. Und immer, wenn er in einer RC-Datei RT_MANIFEST verwendet, steht irgendwo davor auch das #define - und wenn es das schon gäbe, müsste es nicht mehr definiert werden.

    Incocnito schrieb:

    Ich habe die CGRC.exe mal umbenannt, da ich nicht weiß wie man die Rechte entzieht, aber Delphi hat nicht gemeckert (vielleicht habe ich was übersehen).

    Delphi tut nichts, was nicht nötig ist - deshalb ist es ja so ein unglaublich schneller Compiler. Sprich: Wenn du keine Änderungen gemacht hast, die ein Neuerstellen der .res-Datei nötig machen, wird cgrc auch nicht aufgerufen. Über "Projekt erstellen" kannst du das erzwingen.
    Rechte entziehen geht am einfachsten über die Datei-Eigenschaften > Sicherheit. Dort z.B. einfach die Vererbung deaktivieren, dann hat niemand mehr Zugriff; zum Wiederherstellen dann wieder aktivieren.

    Incocnito schrieb:

    habe aber (wenn ich die beiden Logfile vergleiche) keinen Unterschied beim Erzeugen feststellen können

    Ich verwende nur den Parent PID-Filter: Nachschauen, welche Prozess-ID bds.exe hat und das als Parent PID eintragen. Dann taucht beim Compilieren (falls die .res neu erstellt wird) in der ersten Zeile cgrc.exe - Process Start auf, und in der Detail-Spalte sollte die temporäre Datei stehen. Wenn man sich anschaut, was die bds.exe kurz davor macht (Registry-Zugriffe am besten ausblenden): Da wird zunächst mal die Project1.vrc erstellt (also tatsächlich so, wie er es behauptet). Dann wird die wieder geschlossen. Es folgt eine temporäre Datei in %temp%, in die nie etwas geschrieben wird und die auch gleich wieder gelöscht wird. Dann wird der Inhalt der Project1.vrc in eine neue temporäre Datei im Projektverzeichnis kopiert (ReadFile, WriteFile). Mit dieser temporären Datei wird cgrc aufgerufen; wenn es fertig ist, wird die temporäre Datei gelöscht und anschließend die Project1.vrc.

    Incocnito schrieb:

    aber letztlich sind die erzeugten EXEen jetzt mit dem "alten"? DateTimePicker und laufen somit wieder!

    Schön, freut mich, dass es geholfen hat.
    Master of the EDH ;)