1

[RAD Studio XE3 / C++]
この段階では Windows でのみ FMX プロジェクトを実行していますが、USB デバイスが接続されたときと切断されたときにイベントを検出する必要があります。これをうまく実行できる同様の VCL アプリがありますが、Application->HookMainWindow は FMX で公開されていません (VCL のみ)。

これを処理するエレガントな方法はありますか?それとも、それを機能させるために、FMX アプリに VCL をハックする必要がありますか? 将来的に他のプラットフォームをサポートできるように、それを抽象化する必要があると思います。それまでの間、Windows ソリューションを機能させる必要があります。

「VCL ハック」が必要な場合、Fmx アプリ内から vcl::Forms::Application を参照するにはどうすればよいですか?

乾杯。

4

2 に答える 2

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);

お役に立てれば

于 2012-11-23T02:15:01.973 に答える
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();
    }
}

私のために働きます。:)

于 2012-11-23T04:57:57.520 に答える