Load imagelist from CS .net wrapper into Delphi - delphi

I'm writing a CS .net wrapper to be used in a Delphi application and I would like to load images from the "remote" .net lib so I don't need to maintain a "copy" imagelist in Delphi.
Question how do I fetch the imagelist via a TLB?
I think I have 3 options to implement this
on startup of application, fetch imagelist by ref and copy to a local imagelist. This gives me an IUnknown as ref parameter in the TLB, can I use that somehow?
I could use a string/widestring or maybe a stream of some sort, I think that could/would be marshalled as a delphi type.
I could store the imagelist as bitmap and load that in delphi on startup - but who would fancy to do that :)
Any ideas / suggestions a more than welcome.
This is the wrapper method
public bool LoadImageList(ref ImageList imagelist16, ref ImageList imagelist32, ref String ResMsg)
{
ResMsg = "Imagelist could be loaded: ";
try {
imagelist16 = null;
imagelist32 = null;
if (!_initialized) return false;
imagelist16 = VideoOS.Platform.UI.Util.ImageList;
imagelist32 = VideoOS.Platform.UI.Util.ImageList32;
ResMsg = "Images loaded";
return true;
}
catch (Exception e) {
ResMsg = ResMsg + e.Message;
return false;
}
}
This is the Delphi TLB unit
function LoadImageList(var imagelist16: IUnknown; var imagelist32: IUnknown;
var ResMsg: WideString; out pRetVal: WordBool): HResult; stdcall;

"stdole.IPictureDisp" interface as parameter type should do the trick.
COM Interop & image conversion (via API) : http://blogs.msdn.com/b/andreww/archive/2007/07/30/converting-between-ipicturedisp-and-system-drawing-image.aspx

Related

How to dynamically call a form in C++ Builder XE3?

I'm building an application in which Im populating menus using DB. I can create menu items but im having trouble linking "On Click" event to particular forms. I have stored names of the forms classes in my DB and trying to use RTTI to bind them at runtime. Following is the snippet of my code that Im trying to run.
__fastcall TfrmMainMDI::TfrmMainMDI(TComponent *Owner)
: TForm(Owner)
{
// Register 2 form classes
RegisterClass(__classid(TfrmSecurity));
RegisterClass(__classid(TfrmPassword));
}
Now when I try to run following code to call the form it gives "Access violation" error.
TForm *frm = (TForm*)TFormClass(FindClass(formName));
UnicodeString str = frm->Name;
frm->Show();
Do this:
TForm *frm = 0;
Application->CreateForm( TFormClass(FindClass(formName)), &frm );
Then if frm is not null,
frm->Show();
TForm *frm = new TForm(this);
if( frm != NULL )
{
frm->ShowModal();
//or
frm->Show();
}

How do I deserialize an a list of objects from a Memory Stream through WCF

MVC 4.0
I have the following running on a service:
[OperationContract(Name = "GetHierarchyReportContents")]
[FaultContract(typeof(InvalidHierarchyNameException))]
[ServiceKnownType(typeof(Node))]
MemoryStream GetContents();
This function provides a memory stream which contains a list of Node (APINode because of an alias). Essentially, all it does is the following:
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, data.ToList<APINode>());
stream.Seek(0, SeekOrigin.Begin);
return stream;
The following is the definition of Node, which is defined in a namespace to prevent conflict with another node.
[DataContract (Name="Node",Namespace="API")]
[Serializable]
public class Node
{
public Node()
{
}
[DataMember]
public string Name { get; private set; }
}
On my client app, I do the following:
BinaryFormatter bf = new BinaryFormatter();
List<Node> nodes = (List<Node>) bf.Deserialize(client.GetContents());
I am getting the error that says:
Unable to find assembly 'API, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'.
I am using a wsHttpBinding for the client connection.
I must be missing something, perhaps the namespace screws something up. Any ideas?
If the version of the .NET runtime on your client is any different from that which is on your server, binary serialization will likely fail. I would recommend using DataContractSerializer and writing as binary using XmlDictionaryWriter:
var stream = new MemoryStream();
var writer = XmlDictionaryWriter.CreateBinaryWriter(stream);
var serializer = new DataContractSerializer(List<APINode>);
serializer.WriteObject(writer, data.ToList<APINode>());
writer.Flush();
stream.Position = 0;
return stream;
on the client side:
using (var reader = XmlDictionaryReader.CreateBinaryReader(client.GetContents(), XmlDictionaryReaderQuotas.Max))
{
var serializer = new DataContractSerializer(List<Node>);
return (List<Node>)serializer.ReadObject(reader, true);
}

How to get the version number of the Advantage Database Server?

I can easily find out which client version I'm using, but how can I find out the server version?
There is a AdsMgGetInstallInfo ace function and a corresponding stored procedure sp_mgGetInstallInfo.
Do these require some special privileges?
I was expecting to find an TAdsConnection.ServerVersion property, but something like that doesn't seem to exist?
I found the AdsConnection.ServerVersion only for the .NET provider, so it's probably missing in the Delphi Advantage Database wrapper.
But you might try to call the Advantage Management API function AdsMgGetInstallInfo and to the ADS_MGMT_INSTALL_INFO structure receive the aucVersionStr member where should be the Advantage Database Server version. So it might look like this (it's the modified example from the AdsMgGetInstallInfo reference).
Please note, I haven't tested it and I hope you will have all data types and structure definitions.
uses ACE;
function GetServerVersion: string;
var
Size: UNSIGNED16;
MgmtHandle: ADSHANDLE;
ResultValue: UNSIGNED32;
InstallInfo: ADS_MGMT_INSTALL_INFO;
begin
Result := '';
ResultValue := ACE.AdsMgConnect('\\MyExample\Server', nil, nil, #MgmtHandle);
if (ResultValue <> AE_SUCCESS) then
Exit;
Size := SizeOf(ADS_MGMT_INSTALL_INFO);
ResultValue := ACE.AdsMgGetInstallInfo(MgmtHandle, #InstallInfo, #Size);
if (ResultValue <> AE_SUCCESS) then
Exit;
Result := InstallInfo.aucVersionStr;
end;
You should call "sp_mgGetInstallInfo" store procedure.
Here is the Java example:
public static String getAdsVersion() throws ClassNotFoundException,
SQLException {
Connection conn = null;
try {
conn = getAdsConnection();
CallableStatement statement = conn
.prepareCall("{call sp_mgGetInstallInfo()}");
ResultSet resultSet = statement.executeQuery();
resultSet.next();
String version = resultSet.getString("Version");
return version;
} finally {
if (conn != null) {
conn.close();
}
}
}
Here is an example using the sp_mgGetInstallInfo stored procedure method in Delphi, assuming you already have a TAdsQuery component with a valid connection available:
adsQuery.SQL.Clear();
adsQuery.SQL.Add('EXECUTE PROCEDURE sp_mgGetInstallInfo();');
adsQuery.Active := True;
versionStr := adsQuery.FieldByName('Version').AsString;

Deep Cloning in Actionscript

What is the best method to deep clone objects in actionscript?
The best method to do this is by using the ByteArray with the method writeObject. Like this:
function clone(source:Object):* {
var copier:ByteArray = new ByteArray();
copier.writeObject(source);
copier.position = 0;
return(copier.readObject());
}
More information about this, here: http://www.kirupa.com/forum/showpost.php?p=1897368&postcount;=77
If you are trying to deep clone a display object, this is the only way it worked for me :
public static function clone(target:DisplayObject ):DisplayObject {
var bitmapClone:Bitmap = null;
var bitmapData:BitmapData = new BitmapData(target.width,target.height,true,0x00000000);
bitmapData.draw(target);
bitmapClone = new Bitmap(bitmapData);
bitmapClone.smoothing = true;
return bitmapClone;
}
Note that this will only copy visually the object.It will not copy methods or properties.
I used this when i loaded external images, and used them in multiple places.

SubSonic Return ExecuteSingle for Stored Procedure

I wish to return a single ScPollOption item using a Stored Procedure via the code below:
public ScPollOption FetchPollOptionByID(int optionID)
{
StoredProcedure sp = SPs.ScPollOptionGetOptionByID(optionID);
return sp;
}
When working with a query I would use:
ExecuteSingle<ScPollOption>()
but SubSonic only allows for sp.ExecuteTypedList<> and sp.ExecuteScalar<>.
How can I return a single ScPollOption item?
Thanks
Dan
I know it's not terribly attractive, but this would work if you're able to use the LINQ extensions:
sp.ExecuteTypedList<ScPollOption>().FirstOrDefault();
You could also execute an IDataReader and inflate the ScPollOption object manually:
ScPollOption item;
using (IDataReader reader = sp.ExecuteReader())
{
if (reader.Read())
{
item = new ScPollOption();
item.SomeProperty = reader.GetValue(0);
// Set additional properties
}
}
return item;

Resources