home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Runimage / Delphi50 / Source / Property Editors / OCXREG.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-11  |  14.2 KB  |  577 lines

  1. unit OCXReg;
  2.  
  3. interface
  4.  
  5. uses Windows, Activex, SysUtils, ComObj, Classes, Graphics, Controls, Forms,
  6.   Dialogs, TypInfo, DsgnIntf, OleCtrls;
  7.  
  8. type
  9. { TOleControlEditor }
  10.  
  11.   TOleControlEditor = class(TDefaultEditor)
  12.   private
  13.     FVerbs: TStringList;
  14.   protected
  15.     property Verbs: TStringList read FVerbs;
  16.     procedure DoVerb(Verb: Integer); virtual;
  17.   public
  18.     constructor Create(AComponent: TComponent; ADesigner: IFormDesigner); override;
  19.     destructor Destroy; override;
  20.     procedure Edit; override;
  21.     procedure ExecuteVerb(Index: Integer); override;
  22.     function GetVerb(Index: Integer): string; override;
  23.     function GetVerbCount: Integer; override;
  24.   end;
  25.  
  26.   TOleObjectEditor = class
  27.   private
  28.     FPropertyEditor: TPropertyEditor;
  29.   public
  30.     constructor Create(PropertyEditor: TPropertyEditor); virtual;
  31.     function Edit(OleObject: Variant): Variant; virtual;
  32.     property PropertyEditor: TPropertyEditor read FPropertyEditor;
  33.   end;
  34.  
  35.   TOleFontEditor = class(TOleObjectEditor)
  36.     function Edit(OleObject: Variant): Variant; override;
  37.   end;
  38.  
  39.   TOleObjectProperty = class(TPropertyEditor)
  40.     procedure Edit; override;
  41.     function GetAttributes: TPropertyAttributes; override;
  42.     function GetValue: string; override;
  43.     procedure SetValue(const Value: string); override;
  44.     procedure GetProperties(Proc: TGetPropEditProc); override;
  45.   end;
  46.  
  47.   TOleCustomProperty = class(TPropertyEditor)
  48.   public
  49.     function GetAttributes: TPropertyAttributes; override;
  50.     function GetValue: string; override;
  51.     procedure GetValues(Proc: TGetStrProc); override;
  52.     procedure SetValue(const Value: string); override;
  53.   end;
  54.  
  55.   TOlePropPageProperty = class(TPropertyEditor)
  56.   public
  57.     procedure Edit; override;
  58.     function GetAttributes: TPropertyAttributes; override;
  59.   end;
  60.  
  61.   TOleEnumProperty = class(TOrdinalProperty)
  62.   private
  63.     FEnumPropDesc: TEnumPropDesc;
  64.   protected
  65.     property EnumPropDesc: TEnumPropDesc read FEnumPropDesc;
  66.   public
  67.     function GetAttributes: TPropertyAttributes; override;
  68.     function GetValue: string; override;
  69.     procedure GetValues(Proc: TGetStrProc); override;
  70.     procedure Initialize; override;
  71.     procedure SetValue(const Value: string); override;
  72.   end;
  73.  
  74.   TOleObjectEditorClass = class of TOleObjectEditor;
  75.  
  76. procedure RegisterOleObjectEditor(const IID: TIID; const ClassName: string;
  77.   EditorClass: TOleObjectEditorClass);
  78.  
  79. procedure Register;
  80.  
  81. implementation
  82.  
  83. uses DesignConst;
  84.  
  85. type
  86.   POleObjectClassRec = ^TOleObjectClassRec;
  87.   TOleObjectClassRec = record
  88.     Next: POleObjectClassRec;
  89.     IID: TIID;
  90.     ClassName: string;
  91.     EditorClass: TOleObjectEditorClass;
  92.   end;
  93.  
  94. var
  95.   OleObjectClassList: POleObjectClassRec = nil;
  96.  
  97. function GetOleObjectClassRec(OleObject: Variant): POleObjectClassRec;
  98. var
  99.   Dispatch: IDispatch;
  100.   Unknown: IUnknown;
  101. begin
  102.   if VarType(OleObject) = varDispatch then
  103.   begin
  104.     Dispatch := IUnknown(OleObject) as IDispatch;
  105.     if Dispatch <> nil then
  106.     begin
  107.       Result := OleObjectClassList;
  108.       while Result <> nil do
  109.       begin
  110.         if Dispatch.QueryInterface(Result^.IID, Unknown) = 0 then  Exit;
  111.         Result := Result^.Next;
  112.       end;
  113.     end;
  114.   end;
  115.   Result := nil;
  116. end;
  117.  
  118. { TOleControlEditor }
  119.  
  120. constructor TOleControlEditor.Create(AComponent: TComponent;
  121.   ADesigner: IFormDesigner);
  122. begin
  123.   inherited Create(AComponent, ADesigner);
  124.   FVerbs := TStringList.Create;
  125. end;
  126.  
  127. destructor TOleControlEditor.Destroy;
  128. begin
  129.   FVerbs.Free;
  130.   inherited Destroy;
  131. end;
  132.  
  133. procedure TOleControlEditor.DoVerb(Verb: Integer);
  134. begin
  135.   try
  136.     if Verb = -65536 then
  137.       TOleControl(Component).ShowAboutBox
  138.     else
  139.       TOleControl(Component).DoObjectVerb(Verb);
  140.   except
  141.     case Verb of
  142.       -65536: raise Exception.CreateRes(@SNoAboutBoxAvailable);
  143.       OLEIVERB_PROPERTIES: raise Exception.CreateRes(@SNoPropertyPageAvailable);
  144.     else
  145.       raise;
  146.     end;
  147.   end;
  148. end;
  149.  
  150. procedure TOleControlEditor.Edit;
  151. begin
  152.   DoVerb(OLEIVERB_PROPERTIES);
  153. end;
  154.  
  155. procedure TOleControlEditor.ExecuteVerb(Index: Integer);
  156. begin
  157.   DoVerb(Integer(FVerbs.Objects[Index]));
  158. end;
  159.  
  160. function TOleControlEditor.GetVerb(Index: Integer): string;
  161. begin
  162.   Result := FVerbs[Index];
  163. end;
  164.  
  165. function TOleControlEditor.GetVerbCount: Integer;
  166. var
  167.   TI: ITypeInfo;
  168.   W: WideString;
  169.   N: Integer;
  170. begin
  171.   TOleControl(Component).GetObjectVerbs(FVerbs);
  172.   if ((IUnknown(TOleControl(Component).OleObject) as IDispatch).GetTypeInfo(0,0,TI) = S_OK) and
  173.     (TI.GetNames(DISPID_ABOUTBOX, @W, 1, N) = S_OK) and
  174.     (FVerbs.IndexOf(SAboutVerb) = -1) and
  175.     (FVerbs.IndexOfObject(TObject(-65536)) = -1) then
  176.     FVerbs.AddObject(SAboutVerb, TObject(-65536));
  177.   Result := FVerbs.Count;
  178. end;
  179.  
  180. function MapOleCustomProperty(Obj: TPersistent;
  181.   PropInfo: PPropInfo): TPropertyEditorClass;
  182. begin
  183.   Result := nil;
  184.   if (DWORD(PropInfo^.Index) <> $80000000) and (Obj is TOleControl) then
  185.   begin
  186.     if TOleControl(Obj).IsPropPageProperty(PropInfo^.Index) then
  187.       Result := TOlePropPageProperty
  188.     else if TOleControl(Obj).IsCustomProperty(PropInfo^.Index) then
  189.       Result := TOleCustomProperty;
  190.   end;
  191. end;
  192.  
  193. { TOleCustomProperty }
  194.  
  195. function TOleCustomProperty.GetAttributes: TPropertyAttributes;
  196. begin
  197.   Result := [paValueList];
  198. end;
  199.  
  200. function TOleCustomProperty.GetValue: string;
  201. begin
  202.   Result := TOleControl(GetComponent(0)).GetPropDisplayString(
  203.     GetPropInfo^.Index);
  204. end;
  205.  
  206. procedure TOleCustomProperty.GetValues(Proc: TGetStrProc);
  207. var
  208.   Values: TStringList;
  209.   I: Integer;
  210. begin
  211.   Values := TStringList.Create;
  212.   try
  213.     TOleControl(GetComponent(0)).GetPropDisplayStrings(
  214.       GetPropInfo^.Index, Values);
  215.     for I := 0 to Values.Count - 1 do Proc(Values[I]);
  216.   finally
  217.     Values.Free;
  218.   end;
  219. end;
  220.  
  221. procedure TOleCustomProperty.SetValue(const Value: string);
  222. begin
  223.   TOleControl(GetComponent(0)).SetPropDisplayString(
  224.     GetPropInfo^.Index, Value);
  225. end;
  226.  
  227. { TOlePropPageProperty }
  228.  
  229. function TOlePropPageProperty.GetAttributes: TPropertyAttributes;
  230. begin
  231.   Result := [paDialog, paMultiSelect];
  232. end;
  233.  
  234. procedure TOlePropPageProperty.Edit;
  235. var
  236.   PPID: TCLSID;
  237.   OleCtl: TOleControl;
  238.   OleCtls: array of IDispatch;
  239.   Params: TOCPFIParams;
  240.   Caption: WideString;
  241.   I, DispID: Integer;
  242. begin
  243.   SetLength(OleCtls, PropCount);
  244.   for I := 0 to PropCount - 1 do
  245.   begin
  246.     OleCtls[I] := TOleControl(GetComponent(0)).DefaultDispatch;
  247.     if Caption <> '' then Caption := Caption + ', ';
  248.     Caption := Caption + TOleControl(GetComponent(0)).Name;
  249.   end;
  250.   OleCtl := TOleControl(GetComponent(0));
  251.   if OleCtl.PerPropBrowsing <> nil then
  252.   begin
  253.     DispID := GetPropInfo^.Index;
  254.     OleCtl.PerPropBrowsing.MapPropertyToPage(DispID, PPID);
  255.     if not IsEqualCLSID(PPID, GUID_NULL) then
  256.     begin
  257.       with Params do
  258.       begin
  259.         cbStructSize := SizeOf(Params);
  260.         hWndOwner := GetActiveWindow;
  261.         x := 16;
  262.         y := 16;
  263.         lpszCaption := PWideChar(Caption);
  264.         cObjects := PropCount;
  265.         pObjects := @OleCtls[0];
  266.         cPages := 1;
  267.         pPages := @PPID;
  268.         lcid := GetUserDefaultLCID;
  269.         dispidInitialProperty := DispID;
  270.       end;
  271.       OleCreatePropertyFrameIndirect(Params);
  272.     end;
  273.   end;
  274. end;
  275.  
  276. { TOleEnumProperty }
  277.  
  278. function TOleEnumProperty.GetAttributes: TPropertyAttributes;
  279. begin
  280.   Result := [paMultiSelect, paValueList];
  281. end;
  282.  
  283. function TOleEnumProperty.GetValue: string;
  284. begin
  285.   if FEnumPropDesc <> nil then
  286.     Result := FEnumPropDesc.ValueToString(GetOrdValue)
  287.   else
  288.     Result := IntToStr(GetOrdValue);
  289. end;
  290.  
  291. procedure TOleEnumProperty.GetValues(Proc: TGetStrProc);
  292. begin
  293.   if FEnumPropDesc <> nil then FEnumPropDesc.GetStrings(Proc);
  294. end;
  295.  
  296. procedure TOleEnumProperty.Initialize;
  297. begin
  298.   FEnumPropDesc := TOleControl(GetComponent(0)).GetEnumPropDesc(
  299.     GetPropInfo^.Index);
  300. end;
  301.  
  302. procedure TOleEnumProperty.SetValue(const Value: string);
  303. begin
  304.   if FEnumPropDesc <> nil then
  305.     SetOrdValue(FEnumPropDesc.StringToValue(Value)) else
  306.     SetOrdValue(StrToInt(Value));
  307. end;
  308.  
  309. { TOleObjectEditor }
  310.  
  311. constructor TOleObjectEditor.Create(PropertyEditor: TPropertyEditor);
  312. begin
  313.   FPropertyEditor := PropertyEditor;
  314. end;
  315.  
  316. function TOleObjectEditor.Edit(OleObject: Variant): Variant;
  317. begin
  318.   VarClear(Result);
  319. end;
  320.  
  321. { TOleFontEditor }
  322.  
  323. function TOleFontEditor.Edit(OleObject: Variant): Variant;
  324. begin
  325.   VarClear(Result);
  326.   with TFontDialog.Create(Application) do
  327.     try
  328.       OleFontToFont(OleObject, Font);
  329.       Options := Options + [fdForceFontExist];
  330.       if Execute then Result := FontToOleFont(Font);
  331.     finally
  332.       Free;
  333.     end;
  334. end;
  335.  
  336. { TVariantTypeProperty }
  337.  
  338. var
  339.   VarTypeNames: array[0..varByte] of string = ('Unassigned', 'Null', 'Smallint',
  340.     'Integer', 'Single', 'Double', 'Currency', 'Date', 'OleStr', '', '',
  341.     'Boolean', '', '', '', '', '', 'Byte');
  342.  
  343. type
  344.  
  345.   TVariantTypeProperty = class(TNestedProperty)
  346.   public
  347.     function AllEqual: Boolean; override;
  348.     function GetAttributes: TPropertyAttributes; override;
  349.     function GetName: string; override;
  350.     function GetValue: string; override;
  351.     procedure GetValues(Proc: TGetStrProc); override;
  352.     procedure SetValue(const Value: string); override;
  353.    end;
  354.  
  355. function TVariantTypeProperty.AllEqual: Boolean;
  356. var
  357.   i: Integer;
  358.   V1, V2: Variant;
  359. begin
  360.   Result := False;
  361.   if PropCount > 1 then
  362.   begin
  363.     V1 := GetVarValue;
  364.     for i := 1 to PropCount - 1 do
  365.     begin
  366.       V2 := GetVarValueAt(i);
  367.       if VarType(V1) <> VarType(V2) then Exit;
  368.     end;
  369.   end;
  370.   Result := True;
  371. end;
  372.  
  373. function TVariantTypeProperty.GetAttributes: TPropertyAttributes;
  374. begin
  375.   Result := [paMultiSelect, paValueList, paSortList];
  376. end;
  377.  
  378. function TVariantTypeProperty.GetName: string;
  379. begin
  380.   Result := 'Type';
  381. end;
  382.  
  383. function TVariantTypeProperty.GetValue: string;
  384. begin
  385.   case VarType(GetVarValue) and varTypeMask of
  386.     0..varByte: Result := VarTypeNames[VarType(GetVarValue)];
  387.     varString: Result := SString;
  388.   else
  389.     Result := SUnknown;
  390.   end;
  391. end;
  392.  
  393. procedure TVariantTypeProperty.GetValues(Proc: TGetStrProc);
  394. var
  395.   i: Integer;
  396. begin
  397.   for i := 0 to High(VarTypeNames) do
  398.     if VarTypeNames[i] <> '' then
  399.       Proc(VarTypeNames[i]);
  400.   Proc(SString);
  401. end;
  402.  
  403. procedure TVariantTypeProperty.SetValue(const Value: string);
  404.  
  405.   function GetSelectedType: Integer;
  406.   var
  407.     i: Integer;
  408.   begin
  409.     Result := -1;
  410.     for i := 0 to High(VarTypeNames) do
  411.       if VarTypeNames[i] = Value then
  412.       begin
  413.         Result := i;
  414.         break;
  415.       end;
  416.     if (Result = -1) and (Value = SString) then
  417.       Result := varString;
  418.   end;
  419.  
  420. var
  421.   NewType: Integer;
  422.   V: Variant;
  423. begin
  424.   V := GetVarValue;
  425.   NewType := GetSelectedType;
  426.   case NewType of
  427.     varEmpty: VarClear(V);
  428.     varNull: V := NULL;
  429.     -1: raise Exception.CreateRes(@SUnknownType);
  430.   else
  431.     try
  432.       VarCast(V, V, NewType);
  433.     except
  434.       { If it cannot cast, clear it and then cast again. }
  435.       VarClear(V);
  436.       VarCast(V, V, NewType);
  437.     end;
  438.   end;
  439.   SetVarValue(V);
  440. end;
  441.  
  442. { TOleObjectProperty }
  443.  
  444. procedure TOleObjectProperty.Edit;
  445. var
  446.   P: POleObjectClassRec;
  447.   Value: Variant;
  448.   Editor: TOleObjectEditor;
  449. begin
  450.   Value := GetVarValue;
  451.   P := GetOleObjectClassRec(Value);
  452.   if P <> nil then
  453.   begin
  454.     Editor := P^.EditorClass.Create(Self);
  455.     try
  456.       Value := Editor.Edit(Value);
  457.     finally
  458.       Editor.Free;
  459.     end;
  460.     if VarType(Value) = varDispatch then SetVarValue(Value);
  461.   end;
  462. end;
  463.  
  464. function TOleObjectProperty.GetAttributes: TPropertyAttributes;
  465. var
  466.   Value: Variant;
  467. begin
  468.   try
  469.     Value := GetVarValue;
  470.   except
  471.     Value := Null;
  472.   end;
  473.   if GetOleObjectClassRec(Value) <> nil then
  474.     Result := [paMultiSelect, paReadOnly, paDialog] else
  475.     Result := [paMultiSelect, paSubProperties];
  476. end;
  477.  
  478. function TOleObjectProperty.GetValue: string;
  479.  
  480.   function GetVariantStr(const Value: Variant): string;
  481.   begin
  482.     case VarType(Value) of
  483.       varEmpty: Result := '';
  484.       varNull: Result := SNull;
  485.       varBoolean:
  486.         if Value then
  487.           Result := BooleanIdents[True] else
  488.           Result := BooleanIdents[False];
  489.       varCurrency:
  490.         Result := CurrToStr(Value);
  491.     else
  492.       Result := string(Value);
  493.     end;
  494.   end;
  495.  
  496. var
  497.   P: POleObjectClassRec;
  498.   Value: Variant;
  499. begin
  500.   Value := GetVarValue;
  501.   if VarType(Value) <> varDispatch then
  502.     Result := GetVariantStr(Value)
  503.   else
  504.   begin
  505.     P := GetOleObjectClassRec(Value);
  506.     if P <> nil then
  507.       Result := '(' + P^.ClassName + ')' else
  508.       Result := '(OleObject)';
  509.   end
  510. end;
  511.  
  512. procedure TOleObjectProperty.SetValue(const Value: string);
  513.  
  514.   function Cast(var Value: Variant; NewType: Integer): Boolean;
  515.   var
  516.     V2: Variant;
  517.   begin
  518.     Result := True;
  519.     if NewType = varCurrency then
  520.       Result := AnsiPos(CurrencyString, Value) > 0;
  521.     if Result then
  522.     try
  523.       VarCast(V2, Value, NewType);
  524.       Result := (NewType = varDate) or (VarToStr(V2) = VarToStr(Value));
  525.       if Result then Value := V2;
  526.     except
  527.       Result := False;
  528.     end;
  529.   end;
  530.  
  531. var
  532.   V: Variant;
  533.   OldType: Integer;
  534. begin
  535.   OldType := VarType(GetVarValue);
  536.   V := Value;
  537.   if Value = '' then
  538.     VarClear(V) else
  539.   if (CompareText(Value, SNull) = 0) then
  540.     V := NULL else
  541.   if not Cast(V, OldType) then
  542.     V := Value;
  543.   SetVarValue(V);
  544. end;
  545.  
  546. procedure TOleObjectProperty.GetProperties(Proc: TGetPropEditProc);
  547. begin
  548.   Proc(TVariantTypeProperty.Create(Self));
  549. end;
  550.  
  551. procedure RegisterOleObjectEditor(const IID: TIID; const ClassName: string;
  552.   EditorClass: TOleObjectEditorClass);
  553. var
  554.   P: POleObjectClassRec;
  555. begin
  556.   New(P);
  557.   P^.Next := OleObjectClassList;
  558.   P^.IID := IID;
  559.   P^.ClassName := ClassName;
  560.   P^.EditorClass := EditorClass;
  561.   OleObjectClassList := P;
  562. end;
  563.  
  564. { Registration }
  565.  
  566. procedure Register;
  567. begin
  568.   RegisterComponentEditor(TOleControl, TOleControlEditor);
  569.   RegisterPropertyMapper(MapOleCustomProperty);
  570.   RegisterPropertyEditor(TypeInfo(TOleEnum), TOleControl, '', TOleEnumProperty);
  571.   RegisterPropertyEditor(TypeInfo(Variant), nil, '', TOleObjectProperty);
  572.   RegisterPropertyEditor(TypeInfo(SmallInt), TOleControl, 'Cursor', TCursorProperty);
  573.   RegisterOleObjectEditor(IFontDisp, 'OleFont', TOleFontEditor);
  574. end;
  575.  
  576. end.
  577.