Я пытаюсь использовать IVirtualDesktopManager в Turbo Delphi в Windows 10. Я не получаю никаких ошибок, но IsWindowOnCurrentVirtualDesktop и GetWindowDesktopId не возвращают ничего полезного. Кто-нибудь знает, что я здесь делаю неправильно? Благодарю.Использование IVirtualDesktopManager в Delphi
unit VDMUnit;
interface
uses ActiveX, Comobj;
Const
IID_VDM: TGUID ='{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}';
CLSID_VDM: TGUID ='{AA509086-5CA9-4C25-8F95-589D3C07B48A}';
type
{$EXTERNALSYM IVirtualDesktopManager}
IVirtualDesktopManager = interface(IUnknown)
['{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}']
function IsWindowOnCurrentVirtualDesktop(Wnd:cardinal; var IsTrue: boolean): HResult; stdcall;
function GetWindowDesktopId(Wnd:cardinal; pDesktopID: PGUID): HResult; stdcall;
function MoveWindowToDesktop(Wnd:cardinal; DesktopID: PGUID): HResult; stdcall;
end;
function IsOnCurrentDesktop(wnd:cardinal):boolean;
procedure GetWindowDesktopId(Wnd:cardinal; pDesktopID: PGUID);
procedure MoveWindowToDesktop(Wnd:cardinal; DesktopID: PGUID);
implementation
var
vdm:IVirtualDesktopManager;
function IsOnCurrentDesktop(wnd:cardinal):boolean;
begin
CoInitialize(nil);
OleCheck(CoCreateInstance(CLSID_VDM, nil, CLSCTX_INPROC_SERVER,IVirtualDesktopManager,vdm));
OleCheck(vdm.IsWindowOnCurrentVirtualDesktop(wnd,result));
CoUninitialize;
end;
procedure GetWindowDesktopId(Wnd:cardinal; pDesktopID: PGUID);
begin
CoInitialize(nil);
OleCheck(CoCreateInstance(CLSID_VDM, nil, CLSCTX_INPROC_SERVER ,IVirtualDesktopManager,vdm));
OleCheck(vdm.GetWindowDesktopId(wnd,pDesktopID));
CoUninitialize;
end;
procedure MoveWindowToDesktop(Wnd:cardinal; DesktopID: PGUID);
begin
CoInitialize(nil);
OleCheck(CoCreateInstance(CLSID_VDM, nil, CLSCTX_INPROC_SERVER,IVirtualDesktopManager,vdm));
OleCheck(vdm.MoveWindowToDesktop(wnd,DesktopID));
CoUninitialize;
end;
end.
Ok вот простой пример: этот проект просто форма с TMemo и TTimer на нем. Показывает, что Form1.handle нельзя использовать, чтобы проверить, находится ли это окно на текущем рабочем столе. Однако, если вы проверите Application.Handle, тогда вернется правильно false, если вы переключитесь на другой рабочий стол и обратно, чтобы проверить, что написано в заметке. Я нахожу это замечательным, так как я предполагаю, что одно приложение может иметь более одного окна, отображаемого на разных рабочих столах?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ActiveX, Comobj, StdCtrls, ExtCtrls;
const
IID_VDM: TGUID = '{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}';
CLSID_VDM: TGUID ='{AA509086-5CA9-4C25-8F95-589D3C07B48A}';
type
IVirtualDesktopManager = interface(IUnknown)
['{A5CD92FF-29BE-454C-8D04-D82879FB3F1B}']
function IsWindowOnCurrentVirtualDesktop(Wnd: HWND; out IsTrue: BOOL): HResult; stdcall;
function GetWindowDesktopId(Wnd: HWND; out DesktopID: TGUID): HResult; stdcall;
function MoveWindowToDesktop(Wnd: HWND; const DesktopID: TGUID): HResult; stdcall;
end;
type
TForm1 = class(TForm)
Memo1: TMemo;
Timer1: TTimer;
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetVDM: IVirtualDesktopManager;
begin
Result := nil;
OleCheck(CoCreateInstance(CLSID_VDM, nil, CLSCTX_INPROC_SERVER, IVirtualDesktopManager, Result));
end;
function IsOnCurrentDesktop(wnd: HWND): Boolean;
var
value: BOOL;
begin
OleCheck(GetVDM.IsWindowOnCurrentVirtualDesktop(Wnd, value));
Result := value;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if IsOnCurrentDesktop(Form1.Handle) then
Memo1.Lines.Add('Yes')
else
Memo1.Lines.Add('No');
end;
end.
Ваш код работает отлично. Есть несколько странностей. Вместо «кардинала» вы должны использовать «HWND». Ваша оболочка 'GetWindowDesktopId' должна возвращать' TGUID'. Ваша оболочка 'MoveWindowToDesktop' должна принимать const' TGUID'. Но да, ваш код работает отлично. Похоже на недоразумение. Если вы предоставите [mcve], тогда у нас будет возможность выяснить, что это такое. –
Также вы должны объявить параметр 'IsTrue' как' BOOL', а не 'boolean', так как эти типы имеют разные размеры, ваш текущий код перезаписывает стек, и это может привести к сбою. – EugeneK
Спасибо, за исправления! Я заметил что-то еще странное. Когда я проверяю, находится ли форма (form1.handle) на текущем рабочем столе, я всегда получаю ответ «да». Но когда я использую application.handle, я получаю правильные ответы, когда рабочий стол переключается на другой рабочий стол. Кажется, я могу проверить только ручки приложений? –