Взаимодействие DWM из библиотеки DLL
Всем доброе утро.
В настоящее время я пытаюсь написать небольшое приложение, построенное на функциях, доступных через Windows DWM API (например, миниатюры DWM). Одной из таких функций может быть возможность динамического выбора области миниатюры из приложения и ее масштабирования/увеличения. Возможно, это можно сделать из DWM с помощью какой-то функции "set region", но я хотел сначала попробовать свой собственный маршрут, прежде чем заходить слишком далеко в область ПРИКЛАДНОЙ ПРОГРАММНЫЙ ИНТЕРФЕЙС.
Недавно найдяпример для Delphi , я надеялся расширить демонстрацию и построить что-то более конкретное. Я приступил к перемещению кода в приложение Firemonkey FM2
(поскольку я предпочитаю визуальные особенности фреймворка по сравнению с VCL). С помощью нескольких настроек мне удалось построить его, но, к сожалению, похоже, что DWMRegisterThumbnail
не вернет действительный результат при запуске в приложении FMX, несмотря на безупречную работу версии VCL.
Я тогда посмотрел немного дальше и решил дать Гидре шанс. Я скопировал пример рабочей ссылки на плагин Гидры, и создали множество приложений технологии FireMonkey. Я правильно настроил обе части и скомпилировал. DLL загрузилась правильно, и я мог видеть интерфейс плагина VCL внутри хоста FMX, как и ожидалось. Однако при попытке просмотреть миниатюру окна DWM я снова столкнулся с той же проблемой, что и при запуске приложения non-hydra FMX.
Затем я приступил к созданию хоста VCL приложение просто, чтобы убедиться, что это не было проблемой, специфичной для взаимодействия VCL-FMX. Я собрал в VCL узлов, загруженных в модуле VCL, и я снова мог видеть плагин в VCL внутри хост-модулей. Однако еще раз я обнаружил, что не могу просматривать миниатюры из DWM. Очевидно, это не проблема взаимодействия Firemonkey-VCL.
Поэтому я пришел к выводу, что это проблема с запуском кода DWM из DLL. В идеале я хотел бы иметь хост-приложение FMX просто потому, что это проще для меня, чтобы бросить TSelection
над миниатюрой, и иметь дело с масштабированием таким образом (например, очень мало кода, и нет необходимости искать пользовательский компонент), не говоря уже о дополнительных бонусах, таких как MakeScreenshot
.
Итак, чтобы перейти к делу; можно ли вызвать DWM API из плагина Hydra и / или вывести миниатюру DWM на поверхность Firemonkey?
Код, используемый в моем плагине Hydra, идентичен тому, который используется в связанном примере , и код, используемый в моем хосте приложение(ы) основано на простом примере на канале Remobject Youtube.
1 ответ:
Без исходного кода я предположу, что вы не передаете надлежащий дескриптор windows в
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.