Capturing USB Plug / Displug Events in Firemonkey

[RAD Studio XE3 / C ++]
I have an FMX project running on Windows only at this point, but I need to detect events when USB devices are plugged in and unplugged. I have a similar VCL application that can do this well, but Application-> HookMainWindow does not appear in FMX (VCL only).

Is there an elegant way to handle this? Or do I need to hack some VCL stuff into my FMX app to make this work? I would suggest that I need to distract him so that I can support other platforms along the highway. In the meantime, although I need the Windows solution to work.

If the "VCL hack" property is required, how would I refer to vcl :: Forms :: Application from my Fmx application?

Greetings.

+1
source share
2 answers

Can this help using the TMessage method?

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; 

From the stream I am doing something like ...

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

Hope this helps

+1
source

I found a solution, thanks to http://www.haogongju.net/art/1480814 It would be nice to be able to attach some files, but it looks like it needs to be built in.

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

To use it:

 #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(); } } 

Works for me. :)

0
source

Source: https://habr.com/ru/post/1380276/


All Articles