Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: TMessages and TMessageManager on Windows 10


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 4 - Last Post: Sep 21, 2015 8:15 AM Last Post By: Sean Mackey
Sean Mackey

Posts: 5
Registered: 9/15/15
TMessages and TMessageManager on Windows 10  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 10, 2015 8:39 AM
Does anyone know if the TMessages and TMessageManager is working properly on Windows 10? I ran through the example on http://docwiki.embarcadero.com/RADStudio/XE8/en/Sending_and_Receiving_Messages_Using_the_RTL on my Windows 10 PC using C++ Builder XE8 and no matter what I do, it is not displaying a message. Here is my code:

TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
// Captures messages of type TMessage<UnicodeString> and shows a dialog box with
// the string from the message.
void __fastcall TForm1::ShowReceivedMessage(System::TObject* const Sender, System::Messaging::TMessage* const M)
{
    TMessage__1<UnicodeString>* Message = dynamic_cast<TMessage__1<UnicodeString>*>(M);
	if (Message)
        ShowMessage(Message->Value);
}
//---------------------------------------------------------------------------
// Subscribes the ShowReceivedMessage method to TMessage<UnicodeString>
// messages.
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	TMessageManager* MessageManager = TMessageManager::DefaultManager;
	TMetaClass* MessageClass = __classid(TMessage__1<UnicodeString>);
	TMessageListenerMethod ShowReceivedMessagePointer = &(this->ShowReceivedMessage);
	int SubscriptionId = MessageManager->SubscribeToMessage(MessageClass, ShowReceivedMessagePointer);
}
//---------------------------------------------------------------------------
// Sends a TMessage<UnicodeString> message containing the text from the TEdit.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	TMessageManager* MessageManager = TMessageManager::DefaultManager;
	TMessage__1<UnicodeString>* Message = new TMessage__1<UnicodeString>("This is a string message.");
	MessageManager->SendMessage(Sender, Message, true);
}
//---------------------------------------------------------------------------


Let me know if this is broken on Windows 10 please. Thank you all
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: TMessages and TMessageManager on Windows 10  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 10, 2015 12:20 PM   in response to: Sean Mackey in response to: Sean Mackey
Sean wrote:

I ran through the example ... on my Windows 10 PC using C++ Builder XE8
and no matter what I do, it is not displaying a message.

Is the problem that ShowReceivedMessage() is not being called at all, or
that dynamic_cast is returning a NULL pointer? In the latter case, you do
realize that the code is trying to cast a 'const' pointer to a non-const
pointer, don't you? ShowReceivedMessage() should not even be using dynamic_cast
to begin with, since ShowReceivedMessage() is registered for only one message
type, so it can safely use static_cast instead:

void __fastcall TForm1::ShowReceivedMessage(System::TObject* const Sender, 
System::Messaging::TMessage* const M)
{
    const TMessage__1<UnicodeString>* Message = static_cast<const TMessage__1<UnicodeString>*>(M);
    ShowMessage(Message->Value);
}


void __fastcall TForm1::FormCreate(TObject *Sender)

DO NOT ever use the OnCreate event in C++ at all! I realize that you got
this example from Embarcadero's DocWiki, but the example is wrong. OnCreate
is a Delphi idiom that can cause illegal behavior in C++ as it can be triggered
before your derived constructor is called. Your registration code belongs
in the TForm1 constructor instead:

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    int SubscriptionId = TMessageManager::DefaultManager->SubscribeToMessage(__classid(TMessage__1<UnicodeString>), 
&ShowReceivedMessage);
}


And don't forget to unsubscribe when the Form is destroyed (DO NOT use the
OnDestroy event, use the actual destructor):

__fastcall TForm1::~TForm1()
{
    // if you call this version, you need to store SubscriptionId from the 
constructor as a member of the TForm1 class...
    TMessageManager::DefaultManager->Unsubscribe(__classid(TMessage__1<UnicodeString>), 
SubscriptionId, true);
 
    // Otherwise use this version, which does not need the SubscriptionId...
    TMessageManager::DefaultManager->Unsubscribe(__classid(TMessage__1<UnicodeString>), 
&ShowReceivedMessage, true);
}


--
Remy Lebeau (TeamB)
Sean Mackey

Posts: 5
Registered: 9/15/15
Re: TMessages and TMessageManager on Windows 10  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 11, 2015 9:47 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Sean wrote:

I ran through the example ... on my Windows 10 PC using C++ Builder XE8
and no matter what I do, it is not displaying a message.

Is the problem that ShowReceivedMessage() is not being called at all, or
that dynamic_cast is returning a NULL pointer? In the latter case, you do
realize that the code is trying to cast a 'const' pointer to a non-const
pointer, don't you? ShowReceivedMessage() should not even be using dynamic_cast
to begin with, since ShowReceivedMessage() is registered for only one message
type, so it can safely use static_cast instead:

void __fastcall TForm1::ShowReceivedMessage(System::TObject* const Sender, 
System::Messaging::TMessage* const M)
{
    const TMessage__1<UnicodeString>* Message = static_cast<const TMessage__1<UnicodeString>*>(M);
    ShowMessage(Message->Value);
}


void __fastcall TForm1::FormCreate(TObject *Sender)

DO NOT ever use the OnCreate event in C++ at all! I realize that you got
this example from Embarcadero's DocWiki, but the example is wrong. OnCreate
is a Delphi idiom that can cause illegal behavior in C++ as it can be triggered
before your derived constructor is called. Your registration code belongs
in the TForm1 constructor instead:

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    int SubscriptionId = TMessageManager::DefaultManager->SubscribeToMessage(__classid(TMessage__1<UnicodeString>), 
&ShowReceivedMessage);
}


And don't forget to unsubscribe when the Form is destroyed (DO NOT use the
OnDestroy event, use the actual destructor):

__fastcall TForm1::~TForm1()
{
    // if you call this version, you need to store SubscriptionId from the 
constructor as a member of the TForm1 class...
    TMessageManager::DefaultManager->Unsubscribe(__classid(TMessage__1<UnicodeString>), 
SubscriptionId, true)
 
    // Otherwise use this version, which does not need the SubscriptionId...
    TMessageManager::DefaultManager->Unsubscribe(__classid(TMessage__1<UnicodeString>), 
&ShowReceivedMessage, true);
}


--
Remy Lebeau (TeamB)

Thank you Remy. What I am trying to accomplish is have one application tell the other to refresh/update its database and livebindings. I am trying to avoid a timer that constantly calls refresh() and listen for specific paramaters of the database that get updated. I don't know if the TMessage is the best way to accomplish this. Both applications are sharing the same SQLite database, which is basically just a file on the device, and they are both FireMonkey MultiDevice applications. Can you tell me the least expensive way to have a live database feed? It seems no matter which options I check on the TQuery and FDConnection or LiveBindings, it wont stay live. I constantly have to call refresh() in order for it to read in the new database values. If both applications were able to react accordingly, this would be a lot easier.

The main idea is to try and get both applications to know when the database has been updated so the livebindings can be refreshed. However, I dont want all the livebindings to be refreshed, just certain ones that are tied to specific parameters. I am using FireDAC controls for the SQLite database. We are doing queries to insert and update values in the database using a TFDQuery, however, I cant get the livebindings to refresh automatically. Thanks again for all your help. You have great answers on this forum.

Edited by: Sean Mackey on Sep 11, 2015 9:48 AM

Edited by: Sean Mackey on Sep 11, 2015 9:52 AM
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: TMessages and TMessageManager on Windows 10 [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 11, 2015 10:33 AM   in response to: Sean Mackey in response to: Sean Mackey
Sean wrote:

What I am trying to accomplish is have one application tell the other
to refresh/update its database and livebindings.

You cannot use TMessageManager for that. TMessageManager only works for
sending/receiving messages within the same process. It cannot send messages
to other processes.

The main idea is to try and get both applications to know when the
database has been updated so the livebindings can be refreshed.

SQLite supports "Data Change Notification Callbacks":

https://www.sqlite.org/c3ref/update_hook.html

--
Remy Lebeau (TeamB)
Sean Mackey

Posts: 5
Registered: 9/15/15
Re: TMessages and TMessageManager on Windows 10 [Edit]  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Sep 21, 2015 8:15 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Remy Lebeau (TeamB) wrote:
Sean wrote:

What I am trying to accomplish is have one application tell the other
to refresh/update its database and livebindings.

You cannot use TMessageManager for that. TMessageManager only works for
sending/receiving messages within the same process. It cannot send messages
to other processes.

The main idea is to try and get both applications to know when the
database has been updated so the livebindings can be refreshed.

SQLite supports "Data Change Notification Callbacks":

https://www.sqlite.org/c3ref/update_hook.html

--
Remy Lebeau (TeamB)

Thank you Remy. The hooks seem to work between one application and the sqlite database, but not between multiple applications. Is there a way that I can spy on the sqlite database file and see if it has been updated or changed. The idea is not to have a timer constantly running a refresh on the database if it does not need to. I dont know how expensive it would be to have timers on both applications constantly checking for changes versus only updating when it has to. I have multiple controls that values are being set by database values. Let me know if you have any more ideas on how to keep from using a system timer. You have been of great help thus far.

Regards,

Sean M
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02