Getting started working with RemObjects Pascal Script in delphi - delphi

I have just started working with RemObjects Pascal Script. and have been trying to follow the remobjects tutorial.
http://devcenter.remobjects.com/articles/?id={2FFC1EE9-F18D-4B11-9DE4-1BA0A79D0D04}
all was going fine up to the part you run
begin
ShowNewMessage('Show This !');
end.
where it claimed it does not know of it.
but i have it here
procedure Tmainwindow.ceCompile(Sender: TPSScript);
begin
Sender.AddMethod(Self, #Tmainwindow.ShowNewMessage,
'procedure ShowNewMessage(const Message: string);');
end;
procedure ShowNewMessage(const Message: string);
procedure Tmainwindow.ShowNewMessage(const Message: string);
begin
//ShowMessage('ShowNewMessage invoked:'#13#10+Message);
end;
added on the compile event as instructed... it all compiles in delphi but when i run the code from within my executable it says it dont exist.
secondly if i add any plugins to improve the function calls of the script i get this..
please help i realise i may be doing something silly here im new to rem objects.

Well, I tried building the example as shown on that page, and it compiled and ran correctly for me. Try using the example shown at the top of the page, under "The following code will compile and...". Just make sure to leave out the line that replaces the script text.
As for the plugins, it can't register your event types because they refer to object classes that haven't been registered yet. Unfortunately, the PS Plugin system doesn't have any way of automatically resolving dependencies, and the compiler's error message doesn't tell you which type it couldn't find. You'll need the debugger to help you resolve this. But a lot of the basics, including TObject (yes, you have to import it explicitly) are found in TPSImport_Classes.

i have the same Problem. That has nothing to do with the syntax, only with the inclusion of the Forms-Unit template for the script compiler.
Sry, i do not have a solution for that problem, because it even occurs when removing the OnMenuDrawItem and OnMenuAdvancedDrawItem events (which both make Problems).
I use BDS 2006, that might be the problem as it uses advanced Forms source code in comparison to what D7 used (which was the version RO PS was actually made for).
So, remove the Forms unit plugin for the compiler, which also includes the menus unit and try it again, that should "solve" your problem.

Related

Delphi - Wow64EnableWow64FsRedirection Error 32-bit OS

I have a code exmple.
unit Unit1;
interface
uses
...
type
...
function Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection: BOOL): BOOL; stdcall;
var
...
implementation
{$R *.dfm}
uses
...
function Wow64EnableWow64FsRedirection; external kernel32 name 'Wow64EnableWow64FsRedirection';
procedure LaunchOSK;
begin
Wow64EnableWow64FsRedirection(False);
try
ShellExecute(0, 'OPEN', PChar('osk.exe'), nil, nil, SW_SHOWNORMAL);
finally
Wow64EnableWow64FsRedirection(True);
end;
end;
end.
This code works fine in 64-bit OS. However, naturally when you try to use this in a 32-bit OS (XP) you get an error message (The procedure entry point Wow64Enable64FsRedirection could not be located in the dynamic link library kernel32.dll.). If you isolate Wow64EnableWow64FsRedirection and just run ShellExecute it launches fine.
I have beaten my head the past 2 days trying different things I have Googled and not one them of works as far as safely starting OSK in both 32 and 64 bit. Even a well known Delphi guru's suggestion does not work.
I do not need a lecture about disabling Wow64EnableWow64FsRedirection. Since it is temporary no harm no foul.
What I need is understanding how I can take this code and isolate the Wow64Enable64FsRedirection interface procedure and its accompanying implementation part and the necessary parts of the LaunchOSK procedure when the application is running on XP for example. Is this possible??? Compiler statements are useless, right?
If this is not possible then I will have to resort in producing 2 apps (one for XP and the other for 64 bit) which is a last resort.
Thanks in advance.
You can use dynamic loading and simply check whether the GetProcAddress function returns a valid function address.
Or you can use delayed loading and call the imported function only if the OS version and bitness matches necessary requirements.
Your code uses load time linking. The imported function must be present in the system or your executable will not start.
Instead you need to use run time linking. Use LoadLibrary and GetProcAddress to link to the function. If GetProcAddress fails to find the function then it isn't available and of course you don't need to call it because you are on a 32 bit OS.
The right way to do this though is to spawn a 64 bit process which can then launch the OSK process. And if ever you really do need to disable redirection do heed the documentation which tells you to use Wow64DisableWow64FsRedirection.
Finally it's always best to use CreateProcess to launch a process. There's nothing to be gained from involving the shell and file associations. Why ask the shell to call CreateProcess when you can do so directly?
OK, that's normally good advice, but once again, OSK is special. See Delphi - On Screen Keyboard (osk.exe) works on Win32 but fails on Win64.

Delphi ActiveX MSTSCLib

I'm trying to play around with some Delphi ActiveX library for MS-RDP (mstscax.dll), so I imported the library into my project, and started looking for some codes snippets on the web. On a first look, it's pretty obvious, but the lack of examples makes it a little complex.
First the library gives an error on Delphi Seattle, on this line:
property ConnectWithEndpoint: POleVariant1 write Set_ConnectWithEndpoint;
Ok, I commented this line out (not the best solution, I know), but it compiled. Later I tried to change POleVariant1 to OleVariant only, and still compiling.
Ok, after compiled, I tried this code:
var
Form1: TForm1;
RDP: TMsRdpClient8NotSafeForScripting;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
RDP:= TMsRdpClient8NotSafeForScripting.Create(Nil);
RDP.Server:= 'xxxx';
RDP.AdvancedSettings8.RDPPort:= 3389;
RDP.UserName:= 'terminal';
RDP.AdvancedSettings8.ClearTextPassword:= '123456';
RDP.Connect;
if RDP.Connected.ToBoolean = true then
ShowMessage('connected')
else
ShowMessage('error');
end;
I tried some different types for the var RDP, like TMsRdpClient8 only, but still the same problem:
It don't even try to connect! While looking on the sniffer, no tcp connections are made, just nothing happens and the "error" message appears. Any idea about how to work with this guy?
This question intrigued me so I tried to import that ActiveX control and try it myself. It seems to work for me, so I'll explain what I did.
I imported the mstscax.dll ActiveX control then added it to a new package in order to install components onto the tool palette. I immediately ran into the error you did with the ConnectWithEndpoint property. I changed the type in the declaration to OleVariant because the Set_ConnectWithEnpoint property setter function takes an OleVariant. There is clearly something about the type information that our ActiveX importer code is getting confused by. Either way, that change got the file to compile and install the component package. There are now a bunch of TMsRdpClientXXXX components.
Created a new VCL Forms project, then dropped the TMsRdpClient9 component into the form. Added a TButton and then added this code into the button's OnClick handler:
MsRdpClient91.Server := '<some remote server>';
MsRdpClient91.Domain := 'embarcadero.com';
MsRdpClient91.UserName := 'abauer';
MsRdpClient91.Connect;
Once I ran the app, and pressed the button, it connected and the content of the ActiveX control showed the remote server login screen just fine.
I'm running Windows 10, build 10565.
Here's what I'm seeing on my little app I wrote:

Control+Click on function is not working in Delphi XE

In Delphi 7 whenever I control+clicked a function/procedure it took me to that function/procedure. But it is not working in Delphi XE - at least not with all functions. I have a function called Associate in ExtUtils.pas
The function is correctly compiled so the compiler can find the ExtUtils.pas (and of course the ExtUtils is added to the Uses clause and its folder its added in 'Library path'). But when I control+click the function or the unit name, it doesn't take me there.
Any way to fix this?
UPDATE1:
Also, Control+Click on a function (declare in the current unit) does not move the cursor in the INTERFACE section where the function is declared.
UPDATE2:
I temporary put the ExtUtils unit in project's folder and now it works. So, the Control+Click by itself it works but it seems that the IDE has problems finding the unit even it its folder is present in Library Path and Browsing Path.
Similar reports:
http://webcache.googleusercontent.com
http://webcache.googleusercontent.com
http://cc.embarcadero.com/Item/28269
One report right here (see answers below)
New test:
I have fully uninstalled Delphi (and manually delete the files and registry leftovers). Then reinstalled again. NO additional tools except CodeSite were installed, not even the databases. Then I created a new project. It contains a button. When I click the button, it runs the TestMe procedure which is defined in an external PAS file called TestUnit.Pas. I added the path to this library in Library Path and Browsing Path. But the Control+Click on TestMe procedure is still not working! If I hover the mouse over the TestMe procedure, the pop-up says "Declared in TestUnit", where the 'TestUnit' word is a blue link. If I click it I hear a Windows system sound but the IDE doesn't take me there (to the unit).
The TestMe procedure is this:
procedure TestMe;
begin
Beep(800, 500);
end;
If I control+click the Beep procedure, it takes me to Windows.pas. So, this is working.
Please let me know if you have in mind a different test.
UPDATE:
And now it works! Without any apparent reasons! I just open and closed and compiled the project. But I make no changes to Delphi except these two: AutoSave options-> Editor files and Project Options.
UPDATE:
This cannot be!!!
So, now I can access the TestUnit.pas file when I control+click on TestMe procedure.
So, I moved the original PAS file (ExtUtils.pas) that didn't wanted to work in my initial test (before Delphi reinstall) in the same folder where TestUnit.pas is. Guess what: I can open (with control+click) to TestUnit.pas but not the ExtUtils.pas!!!!
Delphi acts so strange and inconsistent!
UPDATE:
I edited ExtUtils.pas and now I cannot open AGAIN TestUnit.pas.
Ken White won't let me say that Delphi could possible have bugs. So I cannot use the 'bug' together with 'Delphi'. Can anybody put these words together for me?
UPDATE:
I totally removed any reference to ExtUtils.pas - so I restored the project to the point where it worked (with TestUnit). But now the bug persists. Even if few seconds before it worked with TestUnit now its not working again.
UPDATE:
Now I realize an important thing: in my source code (in the test project) I have a single line of compilable code:
procedure TForm1.Button1Click(Sender: TObject);
begin
TestMe;
end;
The blue dots does not appear for this code - as it wouldn't have been compiled. In those few minutes when the program worked, I have seen the blue dots.
I have also excluded 'AutoSave options-> Editor files and Project Options' as a possible cause for this issue.
UPDATE:
I have found a way to fix the problem... for few minutes: I move the project and the library in a different folder (any location will do it). The control+click will work for a while. It even works if I put the files back into the original folder. So, it seems that Delphi keeps some kind of cache of some files. As long as the cache is broken and it keeps the cache, control+click won;t work. But when I move the files, it has to recreate that cache so it will work until the issue reappears and it is stored in the cache.
Here we are 5 developers using Delphi 2010 and 2 also using XE and we are experiencing the same thing with the Ctrl-click as you. It seems to stop working randomly. We never could find a pattern or a fix for that. So from time to time we hear swearing coming from cubicles...
When that happens, I use shift-ctrl-F, to do a search.
Sylvain
First, thanks for you all to give hints about this problem. Maybe this is a question long time ago, but at last, after tried many many times, I think the problem cause is, actually, in the "project source code"
IDE version: Delphi XE
please try:
in the Project Options >> Delphi Compiler>>Compiling , ensure:
Debug Information: true
Symbol Reference Info: Reference info
in the Project Source file(dpk file, open by Project >> View Source),
remove {$REFERENCEINFO OFF}
or change to {$REFERENCEINFO ON}
Note that step 2 is very important, even step 1 done, it still can not browse source without step 2.
I'm using Delphi 5 and the Ctrl-click have also problems, i don't know if it still working in the new delphi IDEs but i can go from declaration to implementation using CTRL-SHIFT-UpArrow or DownArrow.
Hope it helps.
There have always been these two distinct options in Delphi:
Library path – used when compiling your app.
Browsing path – used by Code Insight, i.e. when control-clicking identifiers too.
You need to check the second one. It must include the path(s) to the source files you are trying to navigate with Ctrl+Click.
I've found that if I use a record type in the interface section and it's not defined by a type expression, Ctrl-Click and other jumping functions (Ctrl+Shift+Up/Down) won't work.
type
TForm1 = class(TForm)
...
public
Something:record
A, B:integer;
end;
procedure DoSomething;
end;
With the code above I can't jump to implementation of the procedure with Ctrl+Shift+Down. The fix I have to use:
type
TMyRecord = record
A, B:integer;
end;
TForm1 = class(TForm)
...
public
Something:TMyRecord;
procedure DoSomething;
end;
Tested with Delphi XE4.
For future reference. Using Delphi 2010 i have found that a ; preceding virtual in the interface section makes a difference;
function MyProc(): String; overload; virtual;
function MyProc(): Integer; overload; virtual;
// >> ^ <<
This ; character can break the CTRL+Click (code insight) functionality. Compiles fine nonetheless.
I had just made a new groupproject with two projects in Delphi 11. After that I was having problem using Ctrl + Click to jump to functions. I right clicked the groupproject and did "Clean All" and then "Build All" after that it was working for me again.
(Symbol Reference info)This option has no effect unless Debug information and Local symbols (see above) are enabled.
Code completion and code navigation features (Ctrl+Click) work only when Symbol Reference info is set to Reference info.
Solved!
It works for me, change the Code Insight type.
This happens to me quite often, specially when two IDE is opened at the same time.
The way I have found to fix this is:
Clean your project.
List item
Close the IDE.
With the Windows Explorer, navigate to your project.
Search for *.dcu Delete all the .dcu
Launch the IDE and load your project.
Compile it.
At this point, the code navigation (Ctrl+Click) should work.

Automation object leaks memory (TConnectionPoints)

I have an automation object with event support that leaks memory. The FConnectionPoints which comes with the generated source is never freed. When I manually add FConnectionPoints.Free in the destructor, the leak goes away.
I am on Delphi 7, using a FastMM BorlandMM.dll and FastMM_Fulldebugmode.dll.
Steps to reproduce:
Start a new ActiveX Library project
Add a new Automation Object: Name = TestObject; Check "Generate Event support code"
Open the TypeLibrary, add a method to ITestObject, add an event to ITestObjectEvents
Refresh, code will be generated.
Add ShareMem as the first unit in your .dpr file
Save, compile and register this ActiveX Server (Run menu)
Start a new Application project
Put ShareMem as the first unit in your .dpr file
Import Type Library unit: create the unit from the dll you've just created in step 6, and check "Generate Component Wrapper"
In your FormCreate add the following code:
code:
var
lTest: TTestObject;
begin
lTest := TTestObject.Create(nil);
try
lTest.ConnectKind := ckNewInstance;
lTest.Connect;
lTest.Disconnect;
finally
lTest.Free;
end;
end;
Now compile, run and close this application. A memoryleak will be reported.
Question:
Is this a bug in the Delphi code template, am I doing someting wrong, or is it intended to free FConnectionPoints yourself (the help doesn't mention it)?
I don't fully understand the question as I never worked with automation objects but as far as I can see IConnectionPoint is an interface. Interfaces in Delphi are reference-counted (if the implementation inherits from TInterfacedObject, TContainedObject or TAgreggatedObject or implements _AddRef and _Release accordingly), so there should be no memory leak.
For more information on interfaces look at this article.
This chapter from the Delphi Language Guide could help too.
I found this issue to be reported in Quality Central report #1480.
A Sysop asked me to create a new report so I did: report #81288.
This also answers my question: it is a bug in the code template.

Trouble with THTML file GDIPL2A.pas

Running a project and was getting an error saying
"Not enough actual parameters"
The error is in "C:\Program Files\PBear\HTMLComponents\package\GDIPL2A.pas".
The mistake pointed three times to "inherited Create;" lines 260,270 and 278 . In the file "GDIPL2A.pas".the Code is:-
var
err: integer;
begin
inherited Create;
err := GdipCreateBitmapFromScan0(W, H, 0, PixelFormat32bppARGB, nil, fHandle);
if err <> 0 then
raise EGDIPlus.Create('Can''t create bitmap');
end;
I was wondering why it would show an error in "THTML" files, WHICH ARE NOTHING BUT FILES FROM THE INSTALLATION of THTML.I did not even touch THTML files.
Kindly help
Thanks and Regards
Vas
A "Not enough actual parameters" error on "inherited Create;" means that you're trying to call an inherited constructor but it not supplying any parameters. Check the class you're inheriting from and you'll see a Create that requires some parameters. (If the base class doesn't have one, check its parent, and its parent and so on. You'll find one eventually.) It should be pretty obvious once you find the constructor declaration what you need to pass to it.
Your call needs to look something like:
inherited Create(param1, param2);
I have THTML, and it indeed includes GDIPL2A.pas, which is a wrapper around GDIPlus; apparently THTML uses GDIPlus to display embedded images or something.
A quick look at the declaration of TGPImage and TGpBitmap shows the constructor declarations of each:
// TGpImage
public
constructor Create(FileName: string; TmpFile: boolean = False); overload;
constructor Create(IStr: IStream); overload;
// TGpBitmap
public
constructor Create(W, H: Integer); overload;
constructor Create(IStr: IStream); overload;
You'll see that all of the constructors takes at least one or two parameters; your call to inherited Create passes none. However, since the call to inherited is in another constructor it should work (and indeed does on my machine; I just tried rebuilding one of the demos from THTML and it recompiled GDIPL2A.pas fine), You've got something else going on, like a different version of GDIPL2A in your path that the compiler is using instead of the one you're seeing in the IDE's editor.
As to your question, I answered it in the first paragraph above. It's reporting the error in THTML because that's the copy of GDIPL2A that the compiler is using, which may not be the one your code is expecting it to use.
You can fix that by either:
Reordering units in the uses clause of your code so that all calls that cause GDIPL2A to compile are using the same one;
Copy the GDIPL2A your code thinks it's using into your project's source folder, so it will be compiled from there. This will probably break THTML if you're using it in that same project, so be ready for that;
Find and resolve the competing copies of GDIPL2A so that there's only one copy available on the compiler's search path;
Remove the THTML path from your project's search and library paths, if you're not using it in your problem project. You can also, using Project|Options|Packages, prevent THTML from even being loaded when you open the project if you'd like, to make your project load faster.
I don't know if anybody read this anymore but my problem occurred during installing of ThtmlViewer. My solution was to edit the GDIPL2A.pas file. I just added an emty string and a false boolean, so the 3 create statements looked like this:
inherited Create('', False);
And then everything worked fine (at least so far)
(I have an old Delphi 4 on an old Windows Xp on an old PC, not connected to internet)
Kindly
Erling

Resources