Announcement

Collapse
No announcement yet.

PropertyPages zu einem Dateityp hinzufügen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • PropertyPages zu einem Dateityp hinzufügen

    Wenn man im Explorer ein Kontextmenü öffnet und auf Eigenschaften klickt erscheit besagter Dialog. Ähnlich wie man dem Kontextmenü mit dem IShellExtInit-Interface einen Befehl hinzufügen kann, möchte ich jetzt dem Dateityp ein weitere TabPage mit dem IShellPropSheetExt-Interface hinzufügen. Soweit sogut! Wie aber erzeuge ich so eine Seite? Ich brauche ja den Handle zu dieser Seite. Alle Funktionen die einen solchen Handle zurückgeben fordern aber die Beschreibung dieser Seite in einem speziellen STRUCT (PROPSHEETPAGE). Mit diesem STRUCT kann ich nicht anfangen. Wie positioniert man z. B. ein String-Grid? Hat da jemand vielleicht ein Beispiel-Programm-Code (den Code brauche ich unbedingt fürs Verständnis)!

  • #2
    Hallo,

    Windows erwartet, das sich hier ein <b>COM-Objekt</b> im System registriert, das die Interfaces IShellExtInit und IShellPropSheetExt implementiert:
    <pre>
    type
    TMyPropSheet = class(TComObject, IShellExtInit, IShellPropSheetExt)
    function AddPages(lpfnAddPage : TFNAddPropSheetPage; lParam : LPARAM): HResult; stdcall;
    function ReplacePage(uPageID : UINT; lpfnReplaceWith :
    TFNAddPropSheetPage; lParam : LPARAM): HResult; stdcall;
    function Initialize(pidlFolder : PItemIDList; lpdobj : IDataObject;
    hKeyProgID : HKEY): HResult; stdcall;
    end;
    </pre>
    Das Aussehen dieser Seite und die dort sichtbaren Controls werden wie bei der klassischen API-Programmierung üblich als <b>Dialog-Ressource</b> definiert und über <i>{$R foprop.RES}</i> in das Projekt eingebunden. Der Dialog kann am einfachsten mit dem <b>Borland Resource Workshop</b> gestaltet werden - das Tool und eine Kurzbeschreibung ist auf der CDROM (Verzeichnis Borland\RWS) zu meinem Buch <i>Delphi Win32-Lösungen</i> zu finden. Dort taucht aber keine Property Page auf... ;-)<br>
    Windows verwendet die Dialog-Resource als Template, um über die im nachfolgenden Beispiel demonstrierte Zuweisung <i>TPSP.pszTemplate := MakeIntResource(ID_FoldDialog);</i> das Aussehen der Seite zu definieren:
    <pre>
    function TMyPropSheet.AddPages(lpfnAddPage: TFNAddPropSheetPage; lParam:
    LPARAM):
    HResult;
    VAR
    TPSP : TPropSheetPage;
    HPSP : HPropSheetPage;
    begin
    TPSP.dwSize := SizeOf(TPSP);
    TPSP.dwFlags := PSP_USETITLE;
    TPSP.hInstance := hInstance;
    TPSP.pszTemplate := MakeIntResource(ID_FoldDialog);
    TPSP.pszTitle := 'Change Icon 6';
    TPSP.pfnDlgProc := @PropExtDlgProc;
    TPSP.pfnCallBack := NIL;
    TPSP.pcRefParent := nil;
    TPSP.lParam := 0;
    HPSP := CreatePropertySheetPage(TPSP);
    IF HPSP <> NIL THEN
    begin
    IF NOT lpfnAddPage(HPSP, lParam) THEN
    DestroyPropertySheetPage(HPSP);
    end;
    Result := NOERROR;
    end;
    </pre>
    Weiterhin muss das eigene Objekt eine <b>Fensterprozedur</b> für diesen Dialog implementieren. Auch dafür ist ein Beispielprojekt in meinem o.g. Buch

    Comment


    • #3
      Auf diesem Gebiet habe ich noch keine sehr großen Erfahrungen. Alleine die Vorstellungen wie man so eine "Dialog-Ressource" erstellt erscheint mir suspekt. Wie geht so was?

      Ich wäre jedem dankbar der mir sagt wo ich ein komplettes Beispiel, daß zusätzlich noch funktioniert finden kann. Ich bin zwar durch Ihre Erklärung ein Stück weiter gekommen Herr Kosch, aber mir fehlt noch sozusagen das verbindende Mosaik.

      Danke Robert

      Comment


      • #4
        Hallo,

        das folgende Beispiel für eine <b>Dialog-Ressource</b> stammt aus meinem Buch <i>Delphi Win32-Lösungen</i> und wird dort auch näher beschrieben ;-)
        <pre>
        /************************************************** **************************

        beispiel.rc

        produced by Borland Resource Workshop

        ************************************************** ***************************/

        TESTMENU MENU
        {
        POPUP "&Datei"
        {
        MENUITEM "Exit", 101
        }

        POPUP "&Hilfe"
        {
        MENUITEM "&Info über", 201
        }

        }

        ABOUTBOX DIALOG 10, 18, 194, 119
        STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
        CAPTION "Info über GENERIC2.DPR"
        FONT 8, "MS Sans Serif"
        LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
        {
        DEFPUSHBUTTON "OK", 1, 12, 96, 50, 14
        PUSHBUTTON "Cancel", 2, 72, 96, 50, 14
        PUSHBUTTON "Help", 9, 132, 96, 50, 14
        LTEXT "Delphi 2.0-Programm nur aus Win32-API-Funktionen", -1, 9, 12, 176, 13
        LTEXT "Version 1.0", -1, 76, 28, 42, 8
        LTEXT "\xA9 Andreas Kosch 1996", -1, 57, 49, 79, 8
        CTEXT "", 99, 8, 66, 180, 20, SS_CENTER | NOT WS_GROUP
        }
        </pre>
        Wird diese RC-Datei in Delphi 5 dem Projekt hinzugefügt, übersetzt Delphi beim Compilieren die RC-Datei automatisch in die RES-Datei und fügt auch die Einbindung der RES-Datei hinzu.

        Der Dialog wurde - wie am Kommentarblock zu erkennen ist - visuell im <b>Borland Resource Workshop</b> (RWS) entwickelt. Eine Beschreibung der visuellen Konfiguration kann in der Hilfe-Datei des RWS abgerufen werden

        Comment


        • #5
          Hallo Herr Kosch!

          Ich habe nun mit Ihrer Anleitung eine Dialog-Resource im Borland RWS erzeugt. In einem normalen Projekt rufe ich diesen Dialog mit DialogBox(...) auf. Ich habe auch eine DialogProc-Procedure geschrieben die immer Result = False zurück gibt (sonst habe ich keinen Windows-Rahmen!!!). Ich komme aber mit den Nachrichten nich klar die da ankommen (was für Nachrichten?). Mir ist auch nicht ganz so klar wie ich einem Button eine Funktion zuordnen kann (in meinen Dialog tut sich nichts (nicht mal das x zu beenden funktioniert!) und wie ich einem Bitmap auf diesem Dialog ein Bild zuordnen weiß ich erlich gesagt auch nicht so recht (nur Platzhalter wird angezeit). Zudem habe ich ein eigenartiges Verhalten des Dialogs beobachtet. Ist der RWS gestartet erscheint der Dialog normal ist der RWS nicht geladen dann kommt der Dialog auch nicht??? (Bis auf ein mal - da hats geklapt)

          Ich hoffe Sie können mir da weiterhelfen. Tschüss Robert

          Comment


          • #6
            Hallo,

            für die nächste Ausgabe des DER ENTWICKLER habe ich für die Rubrik <i>Tipps & Tricks aus dem Entwicklerforum</i> ein Beispielprojekt für ein eigenes PropertySheet geschrieben, das mit einigen Abbildungen ausführlicher beschrieben werden kann als hier. Ich beschränke mich daher hier wegen des Platzmangels auf die Kurzfassung.

            <b>Dialog-Ressource</b> <br>
            Im Dialog gibt es neben dem statischen Text auch noch ein Feld, dessen Inhalt zur Laufzeit gesetzt werden kann (ID 101). Ein eigener Button kann zusätzlich im PropertySheet angeklickt werden.
            <pre>
            DIALOG_3 DIALOG 6, 15, 161, 115
            STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX
            CAPTION "OSTest PropertySheet-Demo"
            FONT 8, "MS Sans Serif"
            {
            LTEXT "Das ist eine Testseite für den eigenen, mit Delphi 5 entwickelten PropertySheet-Handler", -1, 12, 8, 124, 30
            CONTROL "", -1, "static", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE, 12, 38, 141, 31
            LTEXT "Thread-ID:", -1, 18, 47, 60, 8
            LTEXT "", 101, 68, 46, 60, 8
            PUSHBUTTON "Info", IDC_PUSHBUTTON1, 49, 85, 50, 14
            }
            </pre>
            <b>Fenster-Prozedur</B> <br>
            Die Fenster-Prozedur wertet WM_INITDIALOG aus, um die aktuelle Thread-ID in dem Textfeld anzuzeigen. Außerdem reagiere ich auf WM_COMMAND mit einer MessageBox (da es nur einen Button gibt, muss ich die ID nicht auswerten). Über WM_NOTIFY wird die eigene Fensterprozedur davon informiert, dass der Anwender einen der Standard-Button wie zum Beispiel <b>Übernehmen</b> angeklickt hat.
            <pre>
            function PSPDlgProc(hDlg: HWND; uMessage: UINT;
            wParam: WPARAM; lParam: LPARAM): Boolean; stdcall;
            begin
            Result := True;
            case uMessage of
            WM_INITDIALOG: begin
            SetDlgItemText(hDlg, RC_ThreadId, PChar(sDlgValue));
            end;
            WM_COMMAND : begin
            Windows.MessageBox(hDlg, 'Der Button wurde angeklickt.',
            'OSPropertySheet-Test', 0);
            end;
            WM_NOTIFY : begin
            if PNMHDR(lParam).code = PSN_APPLY then
            Windows.MessageBox(hDlg, 'Änderungen speichern.',
            'OSPropertySheet-Test', 0);
            end;
            else
            Result := False;
            end;
            end;
            </pre>
            <b>Dialog-Template anmelden</b><br>
            Der Aufruf von DialogBox ist nicht notwendig, da Windows selbst den Dialog anzeigt (der Aufruf von <b>CreatePropertySheetPage</b> meldet ja dieses Dialog-Template beim Betriebssystem an). Über <b>pszTemplate</b> wird die Verbindung zum Dialog-Template aus den Ressourcen hergestellt, und <b>pfnDlgProc</b> wird mit dem Zeiger auf die eigene Fenster-Prozedur initialisiert.
            <pre>
            function TOSPropSheetTest.AddPages(lpfnAddPage: TFNAddPropSheetPage;
            lParam: LPARAM): HResult;
            var
            aPSP : TPropSheetPage;
            hPage : HPropSheetPage;
            begin
            FillChar(aPSP, SizeOf(aPSP), #0);
            aPSP.dwSize := SizeOf(aPSP);
            aPSP.dwFlags := PSP_USETITLE;
            aPSP.hInstance := hInstance;
            aPSP.pszTemplate := MakeIntResource(RC_OSTEST);
            aPSP.pszTitle := 'OSTest PropertySheet-Seite';
            aPSP.pfnDlgProc := @PSPDlgProc;
            aPSP.pfnCallback := nil;
            aPSP.lParam := 0;
            hPage := CreatePropertySheetPage(aPSP);
            if hPage <> nil then
            begin
            if not lpfnAddPage(hPage, lParam) then
            DestroyPropertySheetPage(hPage);
            end;
            Result := NOERROR;
            end;
            </pre>
            Beim Aufruf von CreatePropertySheetPage kann in dem Strukturfeld <b>pfnCallback</b> eine eigene Callback-Funktion zugewiesen werden, wenn eine zusätzliche Interaktion während der Anzeige des PropertySheets benötigt wird.

            P.S: Ein Icon muss in WM_INITDIALOG auch auf die klassische Art und Weise aus den Ressourcen eingesetzt werden

            Comment


            • #7
              Danke Herr Kosch,

              ich werde mir die neu Ausgabe von "DER ENTWICKLER" sicherlich besorgen! Mittlerweile ist es mir sogar gelungen, daß ich einem Dateityp meine PropertyPage hinzufügen konnte. Das einzige was mich beunruhigt ist die Tatsache, daß immer der B-RWS geöffnet im Hintergrund sein muß damit die Seite tatsächlich erscheit. Ist der RWS nur eine Demo-Version und brauche ich da einem Vollversion, damit der RWS nicht im ständig laufen muß (ich verwende Delphi 5.0 Enterprises als FULP)?

              Und nochmals danke für Ihre Bemühungen! Robert!!

              Comment


              • #8
                Hallo,

                die Sache mit dem RWS ist mir noch etwas unklar - warum sollte das Tool laufen müssen? Der RWS erleichtert nur das Generieren der RC-Datei mit dem Dialog-Template, für Windows ist nur die in den Ressourcen eingebundene RES-Datei von Interesse. Daher sollte es überhaupt keine Rolle spielen, ob der RWS läuft oder nicht. Mir ist das geschilderte Verhalten auch noch nicht untergekommen. Wie sieht die RC-Datei aus? Passiert das auch, wenn mein Beispiel nachgebaut wird

                Comment


                • #9
                  Hallo ich bin's nochmal,

                  ich habe das Problem falsch umschrieben wie ich auch gerade feststellen mußte. Es liegt nicht am RWS. Immer wenn ich auf der Dialog-Page ein Bitmap, Icon oder über pszIcon dem Tab ein Icon zuweise tritt besagtes verhalten auf. Das Tab der Seite wird zwar zunächst richtig angezeigt, wenn man aber auf das Tab kickt um die Seite zu sehen verschwindet diese und die ursprüngliche Seite "Allgemein" wird nur als leere Seite wieder angezeigt (wenn man den kompletten Dialog verschiebt erscheint sie wieder nochmal, jedoch meine PropertyPage ist einfach weg!!!).

                  Ich hoffe das schildert das Probleme besser (Sorry)!!!!

                  Comment


                  • #10
                    Hallo,

                    ich habe im neu erstellen Delphi-Ordner <b>Download</b> das Beispielprojekt für meinen PropertySheet-Handler abgelegt. Tritt dieser Effekt auch mit diesem Beispiel auf?

                    So wie das Problem geschildert wird, gehe ich davon aus, das entweder die Fensterprozedur oder das Dialog-Template einen Fehler enthält, so dass Windows nach dem ersten "Crash" die Registerseite wieder abräumt.
                    &#10

                    Comment


                    • #11
                      Ich habe mir Ihr Beispiel herunter geladen und mit Delphi als ActiveX-Server eingetragen. Soweit so gut. Das Problem mit den Bitmaps und Icons (auch Tab-Icon) habe ich nicht beobachtet. Jedoch habe ich einen Effekt gesehen wie er auch bei mir auftrat (hab es aber nicht erwähnt --> dachtes das wäre ein Problem). Nach dem anklicken eines Button oder schon nach dem bloßen überstreifen mit dem Cursor (nur Text-Elementen bei freier Fläche nicht) stürzt der Dialog, und meißt dann auch der Explorer hinter, ab. Der Norten CrashGuard meldet eine allgemeine Schutzverletztung und noch so einiges mehr. Windows neu zu starten war dann immer an der Tagesordung.

                      Ich habe in Ihrem Beispiel gelesen: für Windows 2000! Ich verwende Win98 SE --> kann das daran liegen? Ich verstehe zwar nicht was dieses IOSPropSheetTest-Interface soll, aber an sonsten ist mein PropertySheet fast konform mit Ihrem (ich habe aber keine *_TLB.pas)

                      Comment


                      • #12
                        Hallo,

                        das IOSPropSheetTest-Interface resultiert nur aus meiner Faulheit, ich habe das vom Wizard angelegte COM-Objekt nicht aufgeräumt ;-)

                        Im Gegensatz zu Windows 9x nimmt es Windows NT/Windows 2000 genauer, so dass sich eine Problemstelle in jedem Fall unter NT/2000 zu erkennen geben sollte. Windows 9x ist da toleranter, so dass Probleme manchmal unerkannt bleiben. Wenn Windows 98 abstürzt, würde ich diesen Test auf einen anderen Rechner wiederholen. Es kann durchaus sein, dass ein dritter PropertySheet-Handler (der zufällig auf diesem Rechner installiert ist) an dieser Stelle einen Seiteneffekt verursacht.

                        Wenn allein eine Mausbewegung ausreicht, muss der Grund in der Fensterprozedur liegen (WM_MOUSEMOVE-Botschaften etc.).
                        &#10

                        Comment


                        • #13
                          Hallo Herr Kosch,

                          der Fehler tritt sowohl auf mein PC als auch auf meinem Laptop auf. Delphi 5.0 En. hat die Fähigkeit eine ActiveX-Bibl. anzulegen und dort eine Eingenschaftenseite als COM-Object zu erzeugen. Dort wird automatisch ein GUID erzeugt. Kann ich diesen verwenden (oder ist der neu zufall und kann schon vorhanden sein)? Könnte ich sogar diese ganze Seite verwenden (Unit-Formular --> einfach mit Button's usw)?

                          Da ich diesen Freitag auf Win2000 umsteige hoffe ich, daß diese Probleme gegenstandslos werden. Ich werde aber trotzdem der Fensterproz. noch eine Verarbeitung für Maus-Botschaften hinzufügen (vielleicht muß das sein - der Fehler mit dem Klicken könnte da ja vielleicht auch mit zusammen hängen)

                          Comment


                          • #14
                            Hallo,

                            das mit der Eigenschaftsseite vom Delphi-Wizare wäre zu schön um wahr zu sein, aber das Teil ist nur für den Konfigurationsdialog von ActiveX-Controls (alias OCX) zuständig. In diesem Fall verpackt das COM-Objekt seinen eigenen Konfigurationsdialog, der von außen (d.h. von der Entwicklungsumgebung, die dieses OCX einbindet) über die vordefinierten Interfaces aufgerufen werden kann.

                            Für einen PropertySheet-Handler kann das Teil aber leider nicht zweckentfremdet werden :-

                            Comment


                            • #15
                              Hallo Herr Kosch,

                              nach der kleinen Win2000 Umstiegspause bin ich wieder online. Das Problem mit meiner PropertyPage ist fast verschwunden. Ich kann mit der Maus drüber fahren, Buttons anklicken, die Seiten beliebig wechseln und alles ist in Ordung. Der einzige Wermutstropfen: Immer wenn ich den kompletten Dialog schließen stürzt der Explorer ab. Win2000 ist zwar so freundlich ihn wieder automatisch zu starten (nicht so instabil wie Win98) aber das ist ja auch nicht Sinn der Sache.

                              Was ist das nun schon wieder

                              Comment

                              Working...
                              X