[RAD Studio XE3 / C ++]
我有一个仅在此阶段在Windows中运行的FMX项目,但我需要检测连接和断开USB设备时的事件。我有一个类似的VCL应用程序可以做到这一点,但Application-> HookMainWindow不会在FMX(仅VCL)中公开。
有一种优雅的方式来处理这个问题吗?或者我是否必须将一些VCL内容破解到我的FMX应用程序中以使其工作?我想我必须抽象它,以便我可以支持其他平台。与此同时,我需要让Windows解决方案正常运行。
如果需要“VCL hack”,我如何从我的Fmx应用程序中引用vcl :: Forms :: Application?
干杯。
答案 0 :(得分:1)
这有助于使用TMessage方式吗?
type
TMyMessageClass = class(TMessage)
MyProp1 : Integer;
MyProp2 : string;
end;
procedure MyForm.FormCreate(Sender: TObject);
begin
TMessageManager.DefaultManager.SubscribeToMessage(TMyMessageClass, Self.ProcessMessage);
end;
procedure MyForm.ProcessMessage(Sender : TObject; M : TMessage);
begin
if M is TMyMessageClass then
begin
//Do something
end;
end;
从线索我做的事情......
procedure TMyThread.Execute;
var
FMyMessage : TMyMessageClass;
begin
//stuff
Synchronize(
procedure
begin
FMyMessageClass := TMyMessageClass.Create;
FMyMessageClass.MyProp1 := 1;
FMyMessageClass.MyProp2 := 'Hello';
TMessageManager.DefaultManager.SendMessage(nil, FMyMessageClass);
end);
希望这有帮助
答案 1 :(得分:0)
我找到了一个解决方案,感谢http://www.haogongju.net/art/1480814 能够附加一些文件很好,但看起来它必须内联。
<强> SystemEvents.h 强>
#ifndef SystemEventsH
#define SystemEventsH
#include <System.Classes.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Forms.hpp>
#include "DeviceChanged.h"
//---------------------------------------------------------------------------
class TSystemEvents : TObject
{
private:
TDeviceChangedMethod pDeviceChangeHandler;
TForm *pOwnerForm;
#ifdef _Windows
HWND Hwnd; // Save the window handle
LONG OldWndProc;// And remember the old WndProc so we can put it back later
#endif
public:
__fastcall TSystemEvents(TForm *_pForm);
__fastcall ~TSystemEvents();
__property TForm *OwnerForm = {read=pOwnerForm};
#ifdef _Windows
LRESULT __stdcall MessageHandler(Winapi::Messages::TMessage &Message);
#endif // _Windows
__property TDeviceChangedMethod DeviceChangeHandler={read=pDeviceChangeHandler,write=pDeviceChangeHandler};
};
extern TSystemEvents *SystemEvents;
#endif
<强> SystemEvents.cpp 强>
#include <fmx.h>
#include <FMX.Platform.Win.hpp>
#pragma hdrstop
#include "SystemEvents.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#ifdef _Windows
LRESULT __stdcall WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (SystemEvents == NULL)
{
return 0;
}
// This routine can't be a closure because the winapi needs to call it as
// a LONGPTR. So from here I can pass it into the SystemEvents object.
Winapi::Messages::TMessage _Message;
_Message.Msg = msg;
_Message.WParam = wParam;
_Message.LParam = lParam;
return (LRESULT)SystemEvents->MessageHandler(_Message);
}
#endif //_Windows
__fastcall TSystemEvents::TSystemEvents(TForm *_pForm)
{
pOwnerForm = _pForm;
pDeviceChangeHandler = NULL;
#ifdef _Windows
// Owner form handle is in FMX framework, but we want a Hwnd handle:
Hwnd = FmxHandleToHWND(pOwnerForm->Handle);
// Save the original WindowProc address
OldWndProc = GetWindowLongPtr(Hwnd, GWL_WNDPROC);
// Redirect the messages to my own function
SetWindowLongPtr(Hwnd, GWL_WNDPROC, (LONG_PTR)&WindowProc);
#endif
}
__fastcall TSystemEvents::~TSystemEvents()
{
#ifdef _Windows
// Very important we undo our hack before the app finishes
SetWindowLongPtr(Hwnd, GWL_WNDPROC, OldWndProc);
#endif
}
LRESULT __stdcall TSystemEvents::MessageHandler(Winapi::Messages::TMessage &Message)
{
#ifdef _Windows
if (Message.Msg == WM_DEVICECHANGE)
{
if (DeviceChangeHandler != NULL)
{
DeviceChangeHandler(this, new TDeviceChangedMessage(TDeviceChangedMessage::ParamForWin32wParam(Message.WParam)));
return 1;
}
}
return CallWindowProc((WNDPROC)OldWndProc, Hwnd, Message.Msg, Message.WParam, Message.LParam);
#endif
return 0;
}
<强> DeviceChanged.h 强>
#ifndef DeviceChangedH
#define DeviceChangedH
//---------------------------------------------------------------------------
typedef enum {Unknown = 0, DeviceNodesChanged} DeviceChangedParam;
class TDeviceChangedMessage
{
private:
DeviceChangedParam eParam;
public:
TDeviceChangedMessage(DeviceChangedParam _eParam)
{
eParam = _eParam;
}
__property DeviceChangedParam Param={read=eParam};
static DeviceChangedParam __fastcall ParamForWin32wParam(WPARAM _wParam);
};
typedef void __fastcall (__closure *TDeviceChangedMethod)(System::TObject* Sender, TDeviceChangedMessage* M);
#endif
<强> DeviceChanged.cpp 强>
#include <fmx.h>
#include <Dbt.h>
#pragma hdrstop
#include "DeviceChanged.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
DeviceChangedParam __fastcall TDeviceChangedMessage::ParamForWin32wParam(WPARAM _wParam)
{
if (_wParam == DBT_DEVNODES_CHANGED)
return DeviceChangedParam::DeviceNodesChanged;
return DeviceChangedParam::Unknown;
}
使用它:
#include <SystemEvents.h>
TSystemEvents *SystemEvents;
// In Constructor:
{
SystemEvents = new TSystemEvents(this);
SystemEvents->DeviceChangeHandler = OnDeviceChanged;
}
// In Destructor:
{
deletenullify(SystemEvents);
}
// Handler:
void __fastcall TMainForm::OnDeviceChanged(System::TObject* Sender, TDeviceChangedMessage *M)
{
if (M->Param == DeviceChangedParam::DeviceNodesChanged)
{
OnUSBDeviceChanged();
}
}
适合我。 :)