How to fix a delayed declaration in UxTheme - delphi

In Delphi XE UxTheme unit there is the following declaration
function DrawThemeTextEx(hTheme: HTHEME; hdc: HDC; iPartId: Integer; iStateId: Integer;
pszText: LPCWSTR; cchText: Integer; dwTextFlags: DWORD; pRect: PRect;
var pOptions: TDTTOpts): HResult; stdcall;
external themelib name 'DrawThemeTextEx' delayed;
My Windows XP Professional with SP3 does not have such function in the uxtheme.dll (checked with dllexp.exe from http://www.nirsoft.net/utils/dll_export_viewer.html)
It seems like my application does delayed loading of the procedure and fails runtime with the following error:
Project mtgstudio.exe raised exception class EExternalException
with message 'External exception C0FB007F'.
The issue was encountered in JVCL as well but resolved there as per http://andy.jgknet.de/blog/2009/09/once-upon-a-delayed-jvcl-time/
I need UxTheme fixed because they are used by the DevExpress components as well.
Is there a way to patch/fix the UxTheme.pas DrawThemeTextEx declaration to be non-delayed?

The fundamental problem is that this API was introduced in Vista and is not available in XP.
The whole point of the delayed keyword is to allow functions like this to be made available easily to developers who want to take advantage of newer API functions. But to do so the developer typically must also provide fallback implementations for older OS versions, which DevExpress appear to have failed to do.
The bug is therefore not in UxTheme.pas, but in the DevExpress component that calls an API that is not implemented on the platform. The fix is to re-work the DevExpress code to avoid calling this API on XP.
I suggest you contact DevExpress who quite probably already have a fix in their latest versions.

Related

Generics in Delphi and returning a reference to tlist<class>

I still use Delphi XE4 (newest compiler I use of multiple Delphi compilers) and need a specific workaround for the fact they completely hid FClients in TBasicAction in this version. I connect/disconnect clients runtime while setting enabled/disabled (to avoid flicker with ~100+ actions and ui elements) thus this workaround for XE4:
Here's my naive attempt and simply returning the field.
TmscBasicActionCrack = class(TBasicAction)
end;
{$IFDEF mymsDELPHIXE4}
TmscBasicActionHelper = class helper for TBasicAction
public
function Helper_Get_Private_FClients: TList<System.Classes.TBasicActionLink>;
end;
{$ENDIF}
{$IFDEF mymsDELPHIXE4}
//------------------------------------------------------------------------------
function TmscBasicActionHelper.Helper_Get_Private_FClients: TList<System.Classes.TBasicActionLink>;
begin
Result := Self.FClients;
end;
{$ENDIF}
However, I get error
E2003 Undeclared identifier: TList<>
I must admit I never go around to using generics with Delphi since I initially heard of stability problems + I need to maintain compability with Lazarus/FreePascal.
I am aware the most recent versions Delphi has altered class helpers again, but I am for now mostly interested in getting this to work with Delphi XE4
The error is indicating that the TList<T> type is unknown to the compiler. To use it you must include System.Generics.Collections in your uses clause.

Delphi 2005, can't build Indy 10

I'm receiving an error when building the IdMessageHelper.pas unit in the IndyProtocols90 package. All instances of LoadFromStream and LoadFromFile are claiming there is an issue with the signature:
[Error] IdMessageHelper.pas(78): E2250 There is no overloaded version of 'LoadFromStream' that can be called with these arguments
procedure Internal_TIdMessageHelper_LoadFromStream(AMsg: TIdMessage; AStream: TStream;
const AHeadersOnly: Boolean; const AUsesDotTransparency: Boolean);
var
LMsgClient: TIdMessageClient;
begin
if AUsesDotTransparency then begin
AMsg.LoadFromStream(AStream, AHeadersOnly);
end else
begin
// clear message properties, headers before loading
AMsg.Clear;
LMsgClient := TIdMessageClient.Create;
try
Internal_TIdMessageClientHelper_ProcessMessage(LMsgClient, AMsg, AStream, AHeadersOnly, False);
finally
LMsgClient.Free;
end;
end;
end;
I see that IdMessageHelper is new to this version, but the method that's being called (IdMessage.LoadFromStream for example), the arguments for it haven't changed from the last few versions - at least not for the ones that I have the source.
procedure TIdMessage.LoadFromStream(AStream: TStream; const AHeadersOnly: Boolean = False);
var
LMsgClient: TIdMessageClient;
begin
// clear message properties, headers before loading
Clear;
LMsgClient := TIdMessageClient.Create;
try
LMsgClient.ProcessMessage(Self, AStream, AHeadersOnly);
finally
LMsgClient.Free;
end;
end;
I'm pretty sure I removed all previous versions and packages since this was a clean install of D2005.
The IdMessageHelper unit introduces new LoadFrom...() and SaveTo...() methods for the TIdMessage component, to add an AUsesDotTransparency parameter when loading/saving emails.
In Delphi 2005 and later, it does this by defining a class helper (which is a feature introduced in Delphi 2005) to add new methods to the TIdMessage component without having to modify the IdMessage.pas unit itself. This allows Indy to let people use familiar IdMessage1.LoadFrom...() and IdMessage1.SaveTo...() syntax when using the new functionality 1.
Things were done this way so as not to cause interface breaking changes in the IdMessage unit itself. I blogged about this new addition at the time the IdMessageHelper.pas unit was first added to Indy:
New TIdMessage helper
In your case, the error message is complaining about Line 78:
AMsg.LoadFromStream(AStream, AHeadersOnly);
That line is the new 3-parameter TIdMessageHelper.LoadFromStream() method attempting to call the pre-existing 2-parameter TIdMessage.LoadFromStream() method when AUsesDotTransparency is True:
procedure TIdMessage.LoadFromStream(AStream: TStream; const AHeadersOnly: Boolean = False);
I have tested this new class helper in later Delphi versions and it works fine for me. You should not be getting a compiler error, as there should not be any ambiguity.
However, I have not tested the class helper in Delphi 2005 specifically (as I do not have that version installed), so it is possible that the compiler error could be indicating that class helpers (being a new language feature at the time) were still a little buggy, and were fixed later on.
If you can't find the cause of the ambiguity, you can work around the issue by modifying IdMessageHelper.pas to undefine HAS_CLASS_HELPER for Delphi 2005 1, and then recompile Indy again.
1: In older versions of Delphi where class helpers are not available, IdMessageHelper.pas also defines several standalone TIdMessageHelper_LoadFrom...() and TIdMessageHelper_SaveTo...() functions, so people can still utilize the new AUsesDotTransparency functionality, just with a less-desirable calling syntax.
EDIT: it turns out that class helpers were very buggy in Delphi 2005, and were not officially supported until Delphi 2006:
Class helpers have now been formally introduced in the Win32 compiler [in Delphi 2006]. In Delphi 2005 class helpers were not formally available, and although you could use them they were actually quite buggy. It was quite easy to get internal compiler errors while using them, nothing you could complain to with Borland about as this feature was not officially supported.
So, I have now disabled the TIdMessageHelper helper class in Delphi 2005, and have updated the above mentioned blog article accordingly.

CromisIPC compilation error on DELPHI 7

I get the CromisIPC cromis ipc site download and compile/rum successfully the demos and custom project on delphi XE5. Without any error.
But, when I get the same code and put on DELPHI 7 project, I have an error on unit Cromis. AnyValue, an compilation error.
TAnyValue = packed record
private
ValueData: TValueDataType;
{$IFDEF AnyValue_HookingOff}
IntfData : IInterface;
{$ELSE}
{$IFNDEF CPUX64}
Padding : array [0..3] of Byte;
{$ENDIF}
{$ENDIF}
ValueType: TValueType;
function GetAsInt64: Int64; inline;
Exactly on lyne:
ValueData: TValueDataType;
[Error] Cromis.AnyValue.pas(210): ',' or ':' expected but identifier 'ValueData' found
[Error] Cromis.AnyValue.pas(219): 'END' expected but 'FUNCTION' found
I use delphi 7 on a 64 bits windows 7 with a 32 bits VCL project.
The same code compiles on XE5.
What happens here ? any idea ?
tl;dr This code is not designed to work under Delphi 7.
Visibility specifiers are not allowed in Delphi 7 records. The compiler is objecting to the use of private. You can remove that, but then the next problem will be all the methods that are declared on the record. Again, they are not available in Delphi 7.
You might be able to make some headway by switching from packed record to packed object. However, I think it highly unlikely that this will be smooth sailing. Expect a lot of work to make this code compile on Delphi 7. Frankly, you would need to be a Delphi expert to take on this task.
You might try to find an old version of the library that actually supports Delphi 7. You might be able to get one from the library's author. But note that the website says:
All code is Delphi 2006 and upwards compatible. I will not support older Delphi version. If you still use them, then its time to upgrade.
Which leads to the other obvious solution. Upgrade to a modern version of Delphi.
If that is impossible, then you should look for a different library.

Delphi XE5 : SymGetSymFromAddrw error

I am convert component from delphi 5 to delphi xe5`.
I build it completely but still while installation
following error come
The procedure entry point SymGetSymFromAddrW could not be located in
the dynamic link library IMAGEHLP.DLL
SymGetSymFromAddrW has been superceded by SymGetSymFromAddr64 on modern Windows versions. You need to use it instead. It has a very similar definition as SymGetSymFromAddr - just redefine it yourself, and use your version instead:
function SymGetSymFromAddr64(hProcess: THandle; dwAddr: DWord64;
pdwDisplacement: PDWord64; var Symbol: TImagehlpSymbol): Bool; stdcall;
function SymGetSymFromAddr64; external ImagehlpLib name 'SymGetSymFromAddr64W';
See the documentation for SymGetSymFromAddr64 for more info.

Inno setup / pascal scripting - is there any way to use Aero (dwmapi)?

I would like to build a custom setup, with an aero form, but I don't know how to start it.
Is there any way to use DWM API with inno setup?
function dwm(Wnd: HWnd; cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight: integer ): Longint; external 'DwmExtendFrameIntoClientArea#dwmapi.dll stdcall';
DWM API is a native API so you can access it using the DLL Import method.
Then you can call API functions in your script code.
But I would recommend against doing this. Since the DWM only works on Vista or later and it can be disabled by stopping the NT Service. It could prevent your installation from working on a machine that it was designed to work on.
Now that you posted your code...
Original declaration of the API you posted.
HRESULT WINAPI DwmExtendFrameIntoClientArea(
HWND hWnd,
__in const MARGINS *pMarInset
);
My best guess is that it should look like this instead.
type
Margins = record
cxLeftWidth : Integer;
cxRightWidth: Integer;
cyTopHeight: Integer;
cyBottomHeight: Integer;
end;
function DwmExtendFrameIntoClientArea(Wnd: HWnd;
var pMarInset : MARGINS) :
HRESULT;
external 'DwmExtendFrameIntoClientArea#dwmapi.dll cdecl';
you can use the third party tool ISSkin for inno setup
http://isskin.codejock.com/
hope this helps
I would not use such an approach in a setup program, but if you you really need it I would develop it in Delphi, wrap it in a DLL with a simpler API, and call that DLL from InnoSetup.

Resources