来自DLL的DWM交互

时间:2013-02-20 03:25:20

标签: delphi firemonkey dwm remobjects firemonkey-fm2

早上好。

我目前正在尝试编写一个围绕通过Windows DWM API提供的功能(例如DWM缩略图)构建的小型应用程序。一个这样的功能是能够从应用程序中动态选择缩略图区域,并将其放大/放大。可以通过某种“设置区域”功能从DWM执行此操作,但是我在进入API之前,我想先尝试自己的路线。

最近发现an example for Delphi,我曾希望从演示中扩展并构建更具体的内容。我着手将代码移到Firemonkey FM2应用程序(因为我更喜欢框架的视觉功能与VCL相比)。通过一些调整,我设法将其构建,但遗憾的是,尽管VCL版本运行良好,DWMRegisterThumbnail在FMX应用程序中运行时似乎不会返回有效结果。

然后我再看了一下,决定给Hydra一个机会。我将工作的VCL示例复制到Hydra插件,并创建了Firemonkey主机应用程序。我正确设置了两个部分并进行了编译。 DLL加载正确,我可以按预期看到FMX主机内的VCL插件接口。但是,在尝试查看窗口的DWM缩略图时,我再次面临运行非hydra FMX应用程序时遇到的相同问题。

然后我开始创建一个VCL主机应用程序,以确保它不是特定于VCL-FMX交互的问题。我编译了VCL主机,加载到VCL插件中,我再次看到VCL主机内的VCL插件。然而,我仍然发现我无法从DWM查看缩略图。显然,这不是Firemonkey-VCL交互问题。

因此,我已经得出结论,从DLL运行DWM代码是一个问题。理想情况下,我想要一个FMX主机应用程序,因为我更容易在缩略图上放置TSelection,并以这种方式处理缩放(例如,代码非常少,无需查找自定义组件)更不用说额外的奖金,例如MakeScreenshot

所以,切入追逐; 是否可以从Hydra插件调用DWM API,和/或将DWM缩略图输出到Firemonkey表面?

我的Hydra插件中使用的代码与linked example中使用的代码相同,我的宿主应用程序中使用的代码是based upon the simple example on the Remobject Youtube Channel

1 个答案:

答案 0 :(得分:11)

没有源代码,我猜你没有将正确的窗口句柄传递给DwmRegisterThumbnail函数。您可以使用FmxHandleToHWND函数将FMX表单句柄转换为Windows句柄。

尝试修改后的代码版本

unit Unit28;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, Winapi.Windows, Winapi.DwmApi;

type
  TForm28 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FTumbnail: HTHUMBNAIL;
    FPreviewEnabled: Boolean;
    { Private declarations }
    procedure PreviewWindow(const ASource, ADest: HWND; const ARect: TRect);
    procedure PreviewDisable;
  public
    { Public declarations }
  end;

var
  Form28: TForm28;

implementation

uses
  FMX.Platform.Win;


{$R *.fmx}

procedure TForm28.Button1Click(Sender: TObject);
var
  Index: Integer;
  LRect: TRect;
begin
  LRect := Rect(5, 5, Self.Width -20,Self.Height -50);
  //here I'm using a fixed window handle ($000102EE) just a sample
  PreviewWindow($000102EE, FmxHandleToHWND(Self.Handle), LRect);
end;

procedure TForm28.FormCreate(Sender: TObject);
begin
  FPreviewEnabled := False;
end;

procedure TForm28.FormDestroy(Sender: TObject);
begin
  PreviewDisable;
end;

procedure TForm28.PreviewDisable;
begin
  if FPreviewEnabled then
    FPreviewEnabled := NOT Succeeded(DwmUnregisterThumbnail(FTumbnail));
end;

procedure TForm28.PreviewWindow(const ASource, ADest: HWND; const ARect: TRect);
var
  LResult: HRESULT;
  LThumpProp: DWM_THUMBNAIL_PROPERTIES;
begin
  if not DwmCompositionEnabled then begin
    ShowMessage('DWM composition is NOT enabled.');
    Exit;
  end;
  PreviewDisable;
  FPreviewEnabled := Succeeded(DwmRegisterThumbnail(ADest, ASource, @FTumbnail));
  if FPreviewEnabled then
  begin
    LThumpProp.dwFlags := DWM_TNP_SOURCECLIENTAREAONLY or DWM_TNP_VISIBLE or DWM_TNP_OPACITY or DWM_TNP_RECTDESTINATION;
    LThumpProp.fSourceClientAreaOnly := False;
    LThumpProp.fVisible := True;
    LThumpProp.opacity := 200;
    LThumpProp.rcDestination := ARect;
    LResult := DwmUpdateThumbnailProperties(FTumbnail, LThumpProp);
    FPreviewEnabled := (LResult = S_OK);
  end else
    ShowMessage('Cannot link to window  ' + IntToStr(ASource));
end;

end. 

enter image description here