2013-02-20 69 views
2

早上好。DWM與DLL的互動

我目前正在嘗試編寫圍繞通過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 Plugin中使用的代碼與linked example中使用的代碼相同,我的主機應用程序中使用的代碼是based upon the simple example on the Remobject Youtube Channel

+0

DWM工作正常的DLL的這個修改後的版本。你爲什麼隱藏我們的代碼? – 2013-02-20 06:44:17

+0

你已經採取了一條非常複雜的路線來到這裏(Hydra?DLLs?主機應用程序和插件?!)。我也沒有按照你的邏輯理解你爲什麼「總結這是從DLL運行DWM代碼的問題」,特別是因爲它首先失敗了一個簡單的FMX應用程序。下一次,當你遇到第一個問題的時候,問一個SO問題,比如'DWMRegisterThumbnail'不適合你的FMX應用:) – 2013-02-20 12:37:46

+0

這不是隱藏代碼的情況,它只是我不想引用什麼在我鏈接的源文件中,除了我的問題(已經很長)以外,還有一段文字。我認爲這是一個DLL問題,因爲我無法從VCL或FMX主機上運行它。這可能是我錯誤地將代碼移動到所述DLL並完全依賴於此的一個例子,因此我的一個誠實的錯誤。 – 2013-02-20 17:02:17

回答

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

+0

果然,這正是它的原因!感謝RRUZ :) – 2013-02-20 16:56:03