Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi TaskDialogIndirect in einer 64bit Anwendung (https://www.delphipraxis.net/178311-taskdialogindirect-einer-64bit-anwendung.html)

ringli 31. Dez 2013 18:48


TaskDialogIndirect in einer 64bit Anwendung
 
Hallo,

ich habe mir heute mal die TaskDialogIndirect-Demo von Luckie (http://www.michael-puff.de/Programmi...skDialog.shtml) angesehen und diese als Win32- und Win64-Version kompiliert. Die Win32-Version funktioniert offenbar problemlos.

Auch die Win64-Version scheint auf den ersten Blick zu funktionieren. Allerdings tritt hier das Phänomen auf, das nur der Aufruf der einfachen TaskDialog-Funktion funktioniert. Klickt man danach jedoch auf den Button "Ja" um weiter zur Demo der TaskDialogIndirect-Funktion zu gelangen passiert nichts mehr. Keine Fehlermeldung, keine Exception, nichts. Es scheint so als ob der Aufruf der Funktion aus der "comctl32.dll" fehlschlägt. Mehr konnte ich selber leider noch nicht rausfinden.

Scheinbar ist das Problem im Internet nicht unbekannt, jedoch führt der Vorschlag das Manifest anzupassen, nicht zum Erfolg. Ich habe es mit verschiedenen Manifesten und Einstellungen probiert, unter anderem mit diesem hier:
Code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
  version="1.9.0.0"
  processorArchitecture="*"
  name="Win32-API-Tutorials.Win32-API-Tutorials.Sample Code"
  type="win32"/>
<description>Sample Code</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="asInvoker"
          uiAccess="false"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
    </application>
  </compatibility>
<dependency>
    <dependentAssembly>
        <assemblyIdentity type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*" />
    </dependentAssembly>
</dependency>
</assembly>
Ist einem von Euch dieses Problem schon begegnet und konnte es irgendwie lösen? Wie gesagt, die Win32-Version funktioniert problemlos, nur die Win64-Version zickt rum. Daher schliesse ich erstmal einen Fehler in der Demo aus.

Achso, getestet habe ich bei einem Bekannten unter Delphi XE4 Pro da ich selber keine 64bit-Version zur Verfügung habe.

ringli 2. Jan 2014 10:05

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Hat keiner eine Idee? Selbst mit der TMS-Komponente funktioniert das irgendwie nicht.

himitsu 2. Jan 2014 11:01

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Delphi-Quellcode:
  <assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="amd64"
    name="Private.Unknown.MySampleApp"
    type="Win32"/>

Hast du mal probehalber im Manifest auch das Win64 angegeben?
Also amd64 oder ia64, je nachdem, was du hast.

Und ich finde es immer wieder interessant, daß niemand den Namen anpasst oder gar die Version. :stupid:


Ach ja, ich hab zwar sehr oft gesehn, daß bei processorArchitecture ein * angegeben wird,
aber aus leidlicher Erfahrung muß ich sagen, daß man da besser etwas angeben sollte, da Windows das * gern als ungültig erklärt und damit auch das komplette Manifest, bzw. die Anwendung sperrt.
(beim ersten assemblyIdentity, für die Anwendung ... im dependentAssembly stört das * nicht unbedingt ... aber ich hab bisher eigentlich nur Manifeste für Win32-Programme benutzt)

ringli 2. Jan 2014 12:23

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Ja, hatte ich auch schon ausprobiert. Das Ergebnis ist das selbe. Leider. Aber ich kann es heute Abend gerne noch mal ausprobieren.

jaenicke 2. Jan 2014 15:13

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Bei dir steht doch XE4, da sollte doch auch die integrierte Version der Taskdialoge problemlos funktionieren. Also wozu alles selbst deklarieren?
http://docwiki.embarcadero.com/CodeE...alogs_(Delphi)

ringli 2. Jan 2014 18:13

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Beantworte ich dir gerne. Weil ich die Taskdialoge auch ganz gerne in kleinen Starteranwendungen als MessageBox-Ersatz verwende. Und sobald ich die Taskdialoge über die VCL mit einbinde werden aus mal grade 400 kB weit über 1 MB. Jetzt kann man natürlich argumentieren das Speicherplatz nichts mehr kostet, aber ich bin da halt etwas altmodisch. :oops:

Ausserdem interessiert mich das technisch was da wirklich schief läuft.

@himitsu:
Das "amd64" fördert in dem Fall das gleiche zu Tage wie das "*", d.h. vom TaskDialogIndirect ist nach wie vor nichts zu sehen.

ringli 3. Jan 2014 15:00

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe jetzt mal jaenicke's Tip befolgt und mit dem vordefinierten TaskDialogIndirect aus Delphi XE4 ein kleines Testprogramm erstellt. So wie es das Programm im Anhang ist, funktioniert der Aufruf sowohl unter Win32 als auch unter Win64. Zumindest schon mal ein Fortschritt.

Allerdings habe ich jetzt noch das Problem das der durch TaskDialogIndirect erzeugte Hinweisdialog bei Anwendungen ohne Fenster nicht erscheint. Genau das benötige ich aber. Hat hier noch jemand einen Tip wie ich hier ans Ziel komme?

jaenicke 3. Jan 2014 15:42

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Wie du im Debugger siehst, wurde die comctl32.dll nicht geladen, so dass das GetModuleHandle in InitComCtl fehlschlägt. Ein LoadLibrary hilft. ;-) Die exportierte Funktion TaskDialogIndirect wird dennoch nicht gefunden, da müsste man mal schauen warum...

ringli 4. Jan 2014 19:04

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Also ich bin jetzt zumindest schon mal so weit gekommen das es ausreicht die VCL.Controls in die Uses-Klausel des Programmes bzw. der Unit mit aufzunehmen um die Dialoge in einer Anwendung ohne eigenes Fenster anzuzeigen. Allerdings bin ich da jetzt mit meinem Latein am Ende. Ich habe mir da auch schon mal den Initialization-Abschnitt in der VCL-Controls angesehen, aber die VCL ist ja dermassen verstrickt... :cry:

[EDIT]
Die Lösung hat sich jetzt doch einfacher rausgestellt als gedacht:
Delphi-Quellcode:
InitCommonControls;
(aus Winapi.CommCtrl) eingefügt in die DPR-Datei des Projektes und es funktioniert. :)

ringli 5. Jan 2014 10:59

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Zu früh gefreut. :(

Scheinbar hat es gestern nur geklappt weil irgendwas von den anderen Versuchen im Speicher geblieben ist. Nachdem ich es heute nochmal getestet habe funktioniert es nicht mehr richtig. Folgende Konstellationen habe ich getestet:

Anwendung mit Fenster:
  • Win32 = TaskDialogIndirect zeigt ein Fenster an.
  • Win64 = TaskDialogIndirect zeigt ein Fenster an.

Anwendung ohne Fenster:
  • Win32 = TaskDialogIndirect zeigt ein Fenster an.
  • Win64 = TaskDialogIndirect zeigt kein Fenster an.

Als weiteren Versuch habe ich auch noch mal InitCommonControlsEx aufgerufen. Sowohl zusätzlich zu InitCommonControls als auch einzeln. Mir gehen ehrlich gesagt die Ideen aus woran das liegen könnte.

So sieht derzeit die DPR der Anwendung ohne Fenster aus mit der ich teste:
Delphi-Quellcode:
var
  ICC : TInitCommonControlsEx = (
    dwSize : SizeOf(TInitCommonControlsEx);
    dwICC : ICC_LISTVIEW_CLASSES  or
             ICC_TREEVIEW_CLASSES  or
             ICC_BAR_CLASSES       or
             ICC_TAB_CLASSES       or
             ICC_UPDOWN_CLASS      or
             ICC_PROGRESS_CLASS    or
             ICC_HOTKEY_CLASS      or
             ICC_ANIMATE_CLASS     or
             //ICC_WIN95_CLASSES     or
             ICC_DATE_CLASSES      or
             ICC_USEREX_CLASSES    or
             ICC_COOL_CLASSES      or
             ICC_INTERNET_CLASSES  or
             ICC_PAGESCROLLER_CLASS or
             ICC_NATIVEFNTCTL_CLASS or
             ICC_STANDARD_CLASSES  or
             ICC_LINK_CLASS
             );

begin
  InitCommonControls;
  InitCommonControlsEx(ICC);

  tdiMessageDialog('Anwendungsname',
                   'Nachricht',
                   'Nachrichtentext',
                   '<a href="http://www.delphipraxis.net">Delphi-PRAXiS</a>',
                   '',
                   TD_ERROR_ICON,
                   nil,
                   TDCBF_OK_BUTTON,
                   '',
                   ID_OK,
                   TDF_EXPANDED_BY_DEFAULT,
                   0); //Handle
end.
Hat jemand schon dieses Problem bei seinen Projekten gelöst und kann mir helfen?

himitsu 5. Jan 2014 17:13

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Delphi-Quellcode:
begin
  CheckCommonControl(  // oder   IF not InitCommonControl(...) THEN Error...
             ICC_LISTVIEW_CLASSES  or
             ICC_TREEVIEW_CLASSES  or
             ICC_BAR_CLASSES       or
             ICC_TAB_CLASSES       or
             ICC_UPDOWN_CLASS      or
             ICC_PROGRESS_CLASS    or
             ICC_HOTKEY_CLASS      or
             ICC_ANIMATE_CLASS     or
             //ICC_WIN95_CLASSES     or
             ICC_DATE_CLASSES      or
             ICC_USEREX_CLASSES    or
             ICC_COOL_CLASSES      or
             ICC_INTERNET_CLASSES  or
             ICC_PAGESCROLLER_CLASS or
             ICC_NATIVEFNTCTL_CLASS or
             ICC_STANDARD_CLASSES  or
             ICC_LINK_CLASS
             ); // wobei natürlich nur die wirklich benötigten Klassen initialisiert werden wüssten

  tdiMessageDialog('Anwendungsname',
                   'Nachricht',
                   'Nachrichtentext',
                   '<a href="http://www.delphipraxis.net">Delphi-PRAXiS</a>',
                   '',
                   TD_ERROR_ICON,
                   nil,
                   TDCBF_OK_BUTTON,
                   '',
                   ID_OK,
                   TDF_EXPANDED_BY_DEFAULT,
                   0); //Handle
end.
so?

Es sei denn die VCL Läd/Initialisiert noch was Anderes, daß du ohne VCL ebenfalls noch machen musst. (hab da aber, an den wichtigsten Stellen, nichts gesehn)

ringli 5. Jan 2014 18:26

AW: TaskDialogIndirect in einer 64bit Anwendung
 
So nochmal eine kurze Rückmeldung:

Der Fehler saß jetzt tatsächlich vor dem Rechner. :( Ich weiß nicht warum, aber aus irgendwelchen Gründen waren die Laufzeithemes bei der 64bit-Version in den Projektoptionen verstellt. Nachdem ich alle Projektoptionen neu gesetzt habe, reicht tatsächlich der Aufruf von
Delphi-Quellcode:
InitCommonControls;
aus. Ein Aufruf con
Delphi-Quellcode:
CheckCommonControl
der ja auch wieder zur VCL gehört, ist somit nicht notwendig.

Danke nochmal an jaenicke und himitsu die sich die Mühe gemacht haben sich mit meinem Problem auseinanderzusetzen.

himitsu 5. Jan 2014 18:27

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Zitat:

Zitat von ringli (Beitrag 1242284)
Ein Aufruf con
Delphi-Quellcode:
CheckCommonControl
der ja auch wieder zur VCL gehört, ist somit nicht notwendig.

Dann solltest du aber auch den Rückgabewert der Funktion auswerten!

ringli 5. Jan 2014 18:34

AW: TaskDialogIndirect in einer 64bit Anwendung
 
InitCommonControls hat keinen Rückgabewert, aber InitCommonControlsEx gibt einen Boolean zurück. Ich werde das wohl am besten noch umbauen.

himitsu 5. Jan 2014 18:40

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Nicht? :gruebel: (hatte da jetzt die API nicht angeguckt)

Dann will ich jetzt lieber nicht wissen, was InitCommonControl und CheckCommonControl macht.

Soweit ich gesehn hab, ruft CheckCommonControl das InitCommonControl auf.
Und InitCommonControl wendet sich dann an InitCommonControls und wenn das nicht geht (es False zurückgibt), an InitCommonControlsEx .... dachte ich zumindestens so gesehn zu haben.


[add]
Stimmt.

Aber das hättest du sowieso umstellen müssen.
Zitat:

Zitat von InitCommonControls
Under Comctl32.dll version 6.0 and later, InitCommonControls does nothing. Applications must explicitly register all common controls through InitCommonControlsEx.


ringli 5. Jan 2014 18:45

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Ich bin grade dabei, aber welchen ICC-Wert muß ich für die Taskdialoge verwenden? :gruebel:

himitsu 5. Jan 2014 18:55

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Im Notfall kann mehr nicht schaden. Dauert theoretisch nur bissl länger, beim Laden/Initialisieren.

http://msdn.microsoft.com/en-us/libr.../bb775507.aspx
Es kommt wohl darauf an, was alles in dem Dialog verwendet wird.
Wenn ich mir die Liste so anseh, dann sieht es so aus, als wenn mindestens 50% der genannten Dinge nicht benötigt werden. (Animate, Cool, Data, Internet, ListView, Progress, TreeView, UpDown)

ringli 5. Jan 2014 19:06

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Wenn ich das MSDN richtig verstehe, müsste InitCommonControlsEx True zurückgeben wenn es die Controls initialisieren konnte. Bei folgenden Code erscheint aber immer die Messagebox obwohl der Taskdialog danach angezeigt wird. :gruebel:
Delphi-Quellcode:
var
  ICC : TInitCommonControlsEx = (
    dwSize : SizeOf(TInitCommonControlsEx);
    dwICC :
      ICC_LISTVIEW_CLASSES  or
      ICC_TREEVIEW_CLASSES  or
      ICC_BAR_CLASSES       or
      ICC_TAB_CLASSES       or
      ICC_UPDOWN_CLASS      or
      ICC_PROGRESS_CLASS    or
      ICC_HOTKEY_CLASS      or
      ICC_ANIMATE_CLASS     or
      ICC_DATE_CLASSES      or
      ICC_USEREX_CLASSES    or
      ICC_COOL_CLASSES      or
      ICC_INTERNET_CLASSES  or
      ICC_PAGESCROLLER_CLASS or
      ICC_NATIVEFNTCTL_CLASS or
      ICC_STANDARD_CLASSES  or
      ICC_LINK_CLASS
      );

begin
  if not InitCommonControlsEx(ICC) then
    begin
      MessageBox(0, 'InitCommonControlsEx!',
                    'Fehler',
                    MB_OK or MB_ICONSTOP);
      //Halt;
    end;

himitsu 5. Jan 2014 19:38

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Vermutlich wurden nicht Alle und vorallem eine der der anderen (von dir ungenutzen) Klasse nicht initialisiert?

ringli 5. Jan 2014 20:16

AW: TaskDialogIndirect in einer 64bit Anwendung
 
Scheinbar muß
Delphi-Quellcode:
InitCommonControls
trotzdem aufgerufen werden, sonst gibt
Delphi-Quellcode:
InitCommonControlsEx
immer False zurück obwohl der anschliessende Aufruf vom Taskdialog funktioniert.
Ich meine auch in den letzten Tagen bei der Lösungsrecherche etwas gelesen zu haben das es diesbezgl. mal einen Bug in der (Winapi.)CommCtrl.pas gegeben hat oder vielleicht sogar noch gibt.

Jedenfalls sieht der funktionierende Code jetzt so aus:
Delphi-Quellcode:
var
  ICC : TInitCommonControlsEx = (
    dwSize : SizeOf(TInitCommonControlsEx);
    dwICC : ICC_STANDARD_CLASSES);
.
.
.
  InitCommonControls;
  if not InitCommonControlsEx(ICC) then
    begin
      MessageBox(0, 'InitCommonControlsEx!',
                    'Fehler',
                    MB_OK or MB_ICONSTOP);
      Halt;
    end;
.
.
.
[EDIT]
Ich habe den Link wiedergefunden: http://www.entwickler-ecke.de/topic_...ug_5384,0.html

Allerdings habe ich jetzt nicht mehr nachgeprüft ob das immer noch so implementiert ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:12 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz