Unicode controls delphi 2010 - delphi

I have a projects with Delphi 5 use TntUnicode,
And now, i build it in delphi 2010; but i have some problem with Unicode
( delphi 2010 suport Unicode, so i don't use TntUnicode Control );
First: How to replace 2 function
WideCanvasTextExtent(TextBitmap.Canvas, Caption)
;WideCanvasTextOut(TextBitmap.Canvas,0,0,Caption);
Else:
GetText; SetText; IsCaptionStored ;
in Controls units not be declared ;

WideCanvasTextExtent() and WideCanvasTextOut() are third-party functions, probably part of TnT. Just use the Canvas.TextExtent and Canvas.TextOut() methods instead, since they are Unicode now:
TextBitmap.Canvas.TextExtent(Caption);
TextBitmap.Canvas.TextOut(0,0,Caption);
GetText() and SetText() are the getter/setter methods for the TControl.Caption and TControl.Text properties. You should not be calling the methods directly, use the properties instead. Some controls publish the Caption property, and some controls publish the Text property instead.
IsCaptionStored() is used by the TControl.Caption property for controlling DFM streaming. Again, not something you should be calling directly.

Related

Delphi, Handles in TPanel objects

I was reading the source code for tmplayer and MPUI, both media players that use MPlayer as a backend to play media files in Delphi and I noticed here as well as in other older codes that I tried to experiment with that I can't use
Form1.Rectangle1.Handle
or as it is in this example for tmp layer that is trying to pipe the video output at a TPanel
CmdLine := HomeDir + 'mplayer.exe -slave -identify'
+' -wid ' + IntToStr(Form1.Panel1.Handle) + ' -colorkey 0x101010'
+' -nokeepaspect -framedrop -autosync 100' + #32 + Media;
As you may see RAD studio xe6/7 complains that the element does not contain a parameter named Handle. Is this something that used to be valid in older versions but can't be used anymore, and if yes how can I accomplish the same task in a simple Firemonkey form.
EDIT
Ok, so now it is clear to me that the Handle parameter is only applicable for VCL Forms. Trying to rephrase my question,
How can I port that particular line of code (getting the handle of a component) in a Firemonkey form?
Panels and/or Rectangle in Firemonkey doesn't have Handle as member. FireMonkey Handle is member of Form component instead .
You can convert a FireMonkey handle to the platform specific handle with the function : WindowHandleToPlatform, but there is no way to get the handle of a control inside a Form .
Maybe you can replace the Rectangle with another inner form and get the handle of it. Take a look at the FMXEmbeddedForm .

Patched Delphi library for unicode support in TPageProducer callbacks?

I've been using Delphi 2009 with the Indy library (10) that ships and have been upgrading a legacy application that makes heavy use of the TPageProducer. The legacy app was originally written for Delphi 5 / Indy 8.
I'm using the OnHTMLTag property of TPageProducer to specify a function that will handle the HTML transparent tags in my source. My problem was that if I put unicode (Simplified Chinese) characters in the TPageProducer.HTMLDoc property, when the OnHTMLTag callback was called, the TagParams argument contains ?? instead of the expected Chinese characters.
I traced this down to around line 2053 of HTTPApp.pas where we separate out the key / value pairs of the transparent tag:
procedure ExtractHeaderFields(Separators, WhiteSpace: TSysCharSet; Content: PChar;
Strings: TStrings; Decode: Boolean; StripQuotes: Boolean = False);
...
if Decode then
Strings.Add(string(HTTPDecode(AnsiString(DoStripQuotes(ExtractedField)))))
else
Strings.Add(DoStripQuotes(ExtractedField));
...
Everything is fine until we cast the string to an AnsiString and pass it to HTTPDecode, at which point my Strings list contains ?? as does my final TagParams and webpage.
Should there be a version of HTTPDecode that works with Strings instead of AnsiStrings? If so, where might I find this?
For now, I've just disabled the decode routine when I parse my tokens for the TPageProducer, but it isn't a nice fix and would prefer to have a version of this that works with wide characters (if that is even possible).

Export C functions for LabView with c++builder

I have a DLL that I have ported from VC2008 to C++ Builder XE2. The DLL is used in LabVIEW's TestStand.
TestStand, when importing the VC2008 DLL, can see the function names and their arguments. When using the C++ Builder DLL, all its sees are the function names and not the arguments. All exports are C functions and use extern "C" declspec( dllexport ).
Is there a way to get the exports correct?
I have read that adding a TLB file will do the job, if this is true, how do I create a TLB that exports only C functions?
TestStand can read a .c/.cpp file and derive parameters from that file. You still load the DLL and select the function you want to call. You then 'verify' the parameters and select the .c/.cpp file in the dialog. TestStand will find the function with the same name and insert the parameters itself.
The function must be very specific, I had to create a dummy .c file that contained the prototypes as TestStand could not handle the #defines for dllexport and dllimport. It likes a very specific format. For the function:
TESTAPI bool StartTest( long inNumber ) {}
where TESTAPIis either extern "C" __declspec( dllexport ) or extern "C" __declspec( dllimport I had to write the line below in my dummy file:
bool __declspec( dllexport ) StartTest( long inNumber ) {}
That does it.
DLL function parameters cannot be determined from exports alone, unless they are being decorated by the calling convention (which is unusual to do in a DLL). If a TLB (aka a Type Library) solves the problem, then the VC2008 DLL is likely an In-Process ActiveX/COM object rather than a flat C DLL. If so, then in C+Builder you can use the IDE wizards on the "File | New" menu to create an "ActiveX Library" project, then a "COM Object" to add to the library. Then you will have a TLB that you can define your object with, and the IDE will generate stub code that you can fill in with your object's implementation.
If that is not what LabViews is expecting, then I suggest you contact them and ask. If all it needs is a TLB with flat C functions (which is very unusual, because TLB's are object-oriented), then you can omit the "COM Object" portion and just create an "ActiveX Library" project to get a bare-bones TLB, then add your definitions to it as needed, an then add your exports to the project.
From the reference here:
Avoid using the extern "C" syntax to export symbols. The extern "C" syntax prevents the C/C++ DLL Adapter from obtaining type information for function and method parameters."
A little late to the game, but your problem may be that C++ Builder is decorating the exported function with a leading underscore. The TLIB command line utility should help prove this (assuming tlib still ships with C++Builder)
TLIB mydll.lib, mydll.lst
Look at the resulting lst file and see if it contains StartTest or _StartTest. LabView is probably expecting to find a function without the underscore.
You can add a DEF file to your C++Builder project that will suppress the leading underscore. Try this:
Use the __cdecl calling convention instead of __stdcall.
Export plain "C" functions. No C++ classes or member functions.
Make sure you have an extern "C" {} around your function prototypes.
Create a DEF file that aliases the exported functions to a Microsoft
compatible name. Alias the names so they don't contain a leading
underscore. The DEF file will look like this:
EXPORTS
; MSVC name = C++Builder name
StartTest = _StartTest
Foo = _Foo
Bar = _Bar
5- Add the DEF file to your BCB DLL project and rebuild it.
Check out these ancient articles for more details:
http://bcbjournal.org/articles/vol4/0012/Using_Visual_C_DLLs_with_CBuilder.htm
The reverse article (creating C++Builder DLLs that get called from VC++ created applications) is buried in this archive:
http://www.frasersoft.net/program/bcbdev.zip : /articles/bcbdll.htm. It describes the DEF file trick in more detail, plus some other options.
Note that my answer is based on the way thing were in 1998 or so. They may have changed since then. If they have, then the C++Builder command line tools impdef, tlib, tdump, plus the Microsoft equivalents of those tools, should be able to show you exactly what is in your DLL vs the MSVC one.
H^2
I suggest to use ActiveX object: you can create an automation object in C++Builder and in Labview / TestStand you can import this object. If you use automation, in Lavbiew you will have the correct parameter definition. Make sure you are using a set of compatible type variables with Labview / TestStand.
For example, this fragment of code is the implementation of an array passed from Labview to C++:
STDMETHODIMP TCanLibraryImpl::DataDownload(VARIANT Data, long* RV)
{
_precondition_cmodule();
*RV = 0;
TSafeArrayLong1 mySafeArray(Data.parray);
int dLen =mySafeArray.BoundsLength[0];
...
}
In Labview you will pass to this function an array of I64

Loading the output from TOleContainer.SaveAsDocument

I have an existing database with blobs contain OLE compound files. I have a requirement to read these OLE compound files and open them in the Delphi 7 TOleContainer control.
Note that I don't have the source of the app that reads and write to the database. The database remains in active use, so my solution will be used on an ongoing basis, not just for a one-off data extraction.
TOleContainer has a SaveAsDocument method, and by experimentation I have found that, for a given file, this method produces OLE compound files which are identical to those created in the database when that file is added.
However, TOleContainer does NOT have a corresponding LoadFromDocument method. It has other Load* and Create* methods, but none seem capable or suitable for loading the output from SaveAsDocument.
The delphi 7 implementation of SaveAsDocument is this, from the OleCtnrs.pas module:
procedure TOleContainer.SaveAsDocument(const FileName: string);
var
TempStorage: IStorage;
PersistStorage: IPersistStorage;
begin
CheckObject;
if FModSinceSave then SaveObject;
FOleObject.QueryInterface(IPersistStorage, PersistStorage);
if PersistStorage <> nil then
begin
OleCheck(StgCreateDocFile(PWideChar(WideString(Filename)), STGM_READWRITE
or STGM_SHARE_EXCLUSIVE or STGM_CREATE, 0, TempStorage));
OleCheck(OleSave(PersistStorage, TempStorage, False));
PersistStorage.SaveCompleted(nil);
end;
end;
Please provide an implementation of LoadFromDocument which is capable of loading the output from SaveToDocument, and which I can use to patch OleCtnrs.pas. Or else point me to an existing solution.
Thanks!
You have to load the file by using TOleContainer.CreateObjectFromFile. Do not use TOleContainer.LoadFromStream/File, that only works with files that are saved with TOleContainer.SaveToStream/File. Files saved that way get a Delphi specific header containing a four byte code (BDOC) and size (and maybe something more).
According to the documentation for Delphi 2007 (should be the same for ), you can use 'TOleContainer.LoadFromStream'. From the Delphi 7 help file (emphasis mine):
Call LoadFromStream to load an OLE object from a stream. If OldStreamFormat is true, LoadFromStream loads OLE objects saved by a TOleContainer object as well as OLE objects saved using the current format; if OldStreamFormat is false, LoadFromStream will not load OLE objects saved by the library. If there's already an OLE object in the container, it is destroyed and any changes the user made to it are discarded.

How can I read the DOCTYPE SYSTEM identifier with Delphi?

For a document which has a DOCTPYE declaration like
<!DOCTYPE RootElement SYSTEM "file.dtd">
Delphi 2009, using MSXML, reports that the systemId is empty (""):
Assert(Doc.DOMDocument.doctype.systemId <> ''); // fails!
while
Assert(Doc.DOMDocument.doctype.name = 'RootElement'); // ok
correctly verifies that the DOCTYPE name id "RootElement".
Is this a bug in Delphi (or my code) or am I using a version of MSXML which does not support this property?
MSXML's DocumentType implementation is completely missing the DocumentType properties publicId, systemId and internalSubset. MSDN api ref; the missing properties are specifically called out in MS-DOM2CX.
If you need this information you might have to try a different DOM implementation. Here's one. If you can use .NET classes, System.Xml supports it too.
In case ProhibitDTD property is True try setting it to False.
Here's an article with more details.

Resources