1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: DDE sample: client
4 // Author: Julian Smart
5 // Modified by: Jurgen Doornik
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
31 // Settings common to both executables: determines whether
32 // we're using TCP/IP or real DDE.
35 #if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__)
36 #include "mondrian.xpm"
39 #include "wx/datetime.h"
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
48 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
49 EVT_MENU(wxID_EXIT
, MyFrame
::OnExit
)
50 EVT_CLOSE( MyFrame
::OnClose
)
51 EVT_BUTTON( ID_START
, MyFrame
::OnStart
)
52 EVT_CHOICE( ID_SERVERNAME
, MyFrame
::OnServername
)
53 EVT_CHOICE( ID_HOSTNAME
, MyFrame
::OnHostname
)
54 EVT_CHOICE( ID_TOPIC
, MyFrame
::OnTopic
)
55 EVT_BUTTON( ID_DISCONNECT
, MyFrame
::OnDisconnect
)
56 EVT_BUTTON( ID_STARTADVISE
, MyFrame
::OnStartAdvise
)
57 EVT_BUTTON( ID_STOPADVISE
, MyFrame
::OnStopAdvise
)
58 EVT_BUTTON( ID_POKE
, MyFrame
::OnPoke
)
59 EVT_BUTTON( ID_EXECUTE
, MyFrame
::OnExecute
)
60 EVT_BUTTON( ID_REQUEST
, MyFrame
::OnRequest
)
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 // ============================================================================
69 // ============================================================================
71 // ----------------------------------------------------------------------------
73 // ----------------------------------------------------------------------------
75 // The `main program' equivalent, creating the windows and returning the
79 // Create the main frame window
80 m_frame
= new MyFrame(NULL
, _T("Client"));
92 // Define my frame constructor
93 MyFrame
::MyFrame(wxFrame
*frame
, const wxString
& title
)
94 : wxFrame(frame
, wxID_ANY
, title
, wxDefaultPosition
, wxSize(400, 300))
97 SetIcon(wxICON(mondrian
));
100 wxMenu
*file_menu
= new wxMenu
;
102 file_menu
->Append(wxID_EXIT
, _T("&Quit\tCtrl-Q"));
104 wxMenuBar
*menu_bar
= new wxMenuBar
;
106 menu_bar
->Append(file_menu
, _T("&File"));
108 // Associate the menu bar with the frame
109 SetMenuBar(menu_bar
);
111 // set a dialog background
112 SetBackgroundColour(wxSystemSettings
::GetColour(wxSYS_COLOUR_BTNFACE
));
114 // add the controls to the frame
117 IPC_SERVICE
, _T("...")
128 wxBoxSizer
*item0
= new wxBoxSizer( wxVERTICAL
);
130 wxBoxSizer
*item1
= new wxBoxSizer( wxHORIZONTAL
);
132 wxGridSizer
*item2
= new wxGridSizer( 4, 0, 0 );
134 wxButton
*item3
= new wxButton( this, ID_START
, wxT("Connect to server"), wxDefaultPosition
, wxDefaultSize
, 0 );
135 item2
->Add( item3
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
137 wxChoice
*item5
= new wxChoice( this, ID_HOSTNAME
, wxDefaultPosition
, wxSize(100,-1), 2, strs5
, 0 );
138 item2
->Add( item5
, 0, wxALIGN_CENTER
|wxALL
, 5 );
140 wxChoice
*item4
= new wxChoice( this, ID_SERVERNAME
, wxDefaultPosition
, wxSize(100,-1), 2, strs4
, 0 );
141 item2
->Add( item4
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
143 wxChoice
*item6
= new wxChoice( this, ID_TOPIC
, wxDefaultPosition
, wxSize(100,-1), 2, strs6
, 0 );
144 item2
->Add( item6
, 0, wxALIGN_CENTER
|wxALL
, 5 );
146 wxButton
*item7
= new wxButton( this, ID_DISCONNECT
, wxT("Disconnect "), wxDefaultPosition
, wxDefaultSize
, 0 );
147 item2
->Add( item7
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
149 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
151 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
153 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
155 wxButton
*item8
= new wxButton( this, ID_STARTADVISE
, wxT("StartAdvise"), wxDefaultPosition
, wxDefaultSize
, 0 );
156 item2
->Add( item8
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
158 wxButton
*item9
= new wxButton( this, ID_STOPADVISE
, wxT("StopAdvise"), wxDefaultPosition
, wxDefaultSize
, 0 );
159 item2
->Add( item9
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
161 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
163 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
165 wxButton
*item10
= new wxButton( this, ID_EXECUTE
, wxT("Execute"), wxDefaultPosition
, wxDefaultSize
, 0 );
166 item2
->Add( item10
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
168 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
170 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
172 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
174 wxButton
*item11
= new wxButton( this, ID_POKE
, wxT("Poke"), wxDefaultPosition
, wxDefaultSize
, 0 );
175 item2
->Add( item11
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
177 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
179 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
181 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
183 wxButton
*item12
= new wxButton( this, ID_REQUEST
, wxT("Request"), wxDefaultPosition
, wxDefaultSize
, 0 );
184 item2
->Add( item12
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
186 item2
->Add( 20, 20, 0, wxALIGN_CENTER
|wxALL
, 5 );
188 item1
->Add( item2
, 1, wxALIGN_CENTER
|wxALL
, 5 );
190 item0
->Add( item1
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
192 wxStaticBox
*item14
= new wxStaticBox( this, -1, wxT("Client log") );
193 wxStaticBoxSizer
*item13
= new wxStaticBoxSizer( item14
, wxVERTICAL
);
195 wxTextCtrl
*item15
= new wxTextCtrl( this, ID_LOG
, wxT(""), wxDefaultPosition
, wxSize(500,140), wxTE_MULTILINE
);
196 item13
->Add( item15
, 1, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
198 item0
->Add( item13
, 0, wxGROW
|wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
200 this->SetSizer( item0
);
201 item0
->SetSizeHints( this );
205 GetServername()->SetSelection(0);
206 GetHostname()->SetSelection(0);
207 GetTopic()->SetSelection(0);
208 wxLogTextCtrl
*logWindow
= new wxLogTextCtrl(GetLog());
209 delete wxLog
::SetActiveTarget(logWindow
);
210 wxLogMessage(_T("Click on Connect to connect to the server"));
214 void MyFrame
::Enable()
216 GetStart()->Enable(m_client
== NULL
);
217 GetServername()->Enable(m_client
== NULL
);
218 GetHostname()->Enable(m_client
== NULL
);
219 GetTopic()->Enable(m_client
== NULL
);
220 GetDisconnect()->Enable(m_client
&& m_client
->IsConnected() != NULL
);
221 GetStartAdvise()->Enable(m_client
&& m_client
->IsConnected() != NULL
);
222 GetStopAdvise()->Enable(m_client
&& m_client
->IsConnected() != NULL
);
223 GetExecute()->Enable(m_client
&& m_client
->IsConnected() != NULL
);
224 GetPoke()->Enable(m_client
&& m_client
->IsConnected() != NULL
);
225 GetRequest()->Enable(m_client
&& m_client
->IsConnected() != NULL
);
228 void MyFrame
::OnClose(wxCloseEvent
& event
)
238 void MyFrame
::OnExit(wxCommandEvent
& WXUNUSED(event
))
243 void MyFrame
::OnStart(wxCommandEvent
& WXUNUSED(event
))
245 // Connect to the client
246 wxString servername
= GetServername()->GetStringSelection();
247 wxString hostname
= GetHostname()->GetStringSelection();
248 wxString topic
= GetTopic()->GetStringSelection();
250 m_client
= new MyClient
;
251 bool retval
= m_client
->Connect(hostname
, servername
, topic
);
253 wxLogMessage(_T("Client host=\"%s\" port=\"%s\" topic=\"%s\" %s"),
254 hostname
.c_str(), servername
.c_str(), topic
.c_str(),
255 retval ?
_T("connected") : _T("failed to connect"));
265 void MyFrame
::OnServername( wxCommandEvent
& WXUNUSED(event
) )
267 if (GetServername()->GetStringSelection() == _T("..."))
269 wxString s
= wxGetTextFromUser(_T("Specify the name of the server"),
270 _T("Server Name"), _(""), this);
271 if (!s
.IsEmpty() && s
!= IPC_SERVICE
)
273 GetServername()->Insert(s
, 0);
274 GetServername()->SetSelection(0);
279 void MyFrame
::OnHostname( wxCommandEvent
& WXUNUSED(event
) )
281 if (GetHostname()->GetStringSelection() == _T("..."))
283 wxString s
= wxGetTextFromUser(_T("Specify the name of the host (ignored under DDE)"),
284 _T("Host Name"), _(""), this);
285 if (!s
.IsEmpty() && s
!= IPC_HOST
)
287 GetHostname()->Insert(s
, 0);
288 GetHostname()->SetSelection(0);
293 void MyFrame
::OnTopic( wxCommandEvent
& WXUNUSED(event
) )
295 if (GetTopic()->GetStringSelection() == _T("..."))
297 wxString s
= wxGetTextFromUser(_T("Specify the name of the topic"),
298 _T("Topic Name"), _(""), this);
299 if (!s
.IsEmpty() && s
!= IPC_TOPIC
)
301 GetTopic()->Insert(s
, 0);
302 GetTopic()->SetSelection(0);
307 void MyFrame
::OnDisconnect(wxCommandEvent
& WXUNUSED(event
))
312 void MyFrame
::Disconnect()
319 void MyFrame
::OnStartAdvise(wxCommandEvent
& WXUNUSED(event
))
321 m_client
->GetConnection()->StartAdvise(_T("something"));
324 void MyFrame
::OnStopAdvise(wxCommandEvent
& WXUNUSED(event
))
326 m_client
->GetConnection()->StopAdvise(_T("something"));
329 void MyFrame
::OnExecute(wxCommandEvent
& WXUNUSED(event
))
331 if (m_client
->IsConnected())
333 wxString s
= _T("Date");
335 m_client
->GetConnection()->Execute((wxChar
*)s
.c_str());
336 m_client
->GetConnection()->Execute((wxChar
*)s
.c_str(), (s
.Length() + 1) * sizeof(wxChar
));
337 #if wxUSE_DDE_FOR_IPC
338 wxLogMessage(_T("DDE Execute can only be used to send text strings, not arbitrary data.\nThe type argument will be ignored, text truncated, converted to Unicode and null terminated."));
341 bytes
[0] = '1'; bytes
[1] = '2'; bytes
[2] = '3';
342 m_client
->GetConnection()->Execute((wxChar
*)bytes
, 3, wxIPC_PRIVATE
);
346 void MyFrame
::OnPoke(wxCommandEvent
& WXUNUSED(event
))
348 if (m_client
->IsConnected())
350 wxString s
= wxDateTime
::Now().Format();
351 m_client
->GetConnection()->Poke(_T("Date"), (wxChar
*)s
.c_str());
352 s
= wxDateTime
::Now().FormatTime() + _T(" ") + wxDateTime
::Now().FormatDate();
353 m_client
->GetConnection()->Poke(_T("Date"), (wxChar
*)s
.c_str(), (s
.Length() + 1) * sizeof(wxChar
));
355 bytes
[0] = '1'; bytes
[1] = '2'; bytes
[2] = '3';
356 m_client
->GetConnection()->Poke(_T("bytes[3]"), (wxChar
*)bytes
, 3, wxIPC_PRIVATE
);
360 void MyFrame
::OnRequest(wxCommandEvent
& WXUNUSED(event
))
362 if (m_client
->IsConnected())
365 m_client
->GetConnection()->Request(_T("Date"));
366 m_client
->GetConnection()->Request(_T("Date+len"), &size
);
367 m_client
->GetConnection()->Request(_T("bytes[3]"), &size
, wxIPC_PRIVATE
);
371 // ----------------------------------------------------------------------------
373 // ----------------------------------------------------------------------------
374 MyClient
::MyClient() : wxClient()
379 bool MyClient
::Connect(const wxString
& sHost
, const wxString
& sService
, const wxString
& sTopic
)
381 // suppress the log messages from MakeConnection()
384 m_connection
= (MyConnection
*)MakeConnection(sHost
, sService
, sTopic
);
385 return m_connection
!= NULL
;
388 wxConnectionBase
*MyClient
::OnMakeConnection()
390 return new MyConnection
;
393 void MyClient
::Disconnect()
397 m_connection
->Disconnect();
400 wxGetApp().GetFrame()->Enable();
401 wxLogMessage(_T("Client disconnected from server"));
405 MyClient
::~MyClient()
410 // ----------------------------------------------------------------------------
412 // ----------------------------------------------------------------------------
414 void MyConnection
::Log(const wxString
& command
, const wxString
& topic
,
415 const wxString
& item
, wxChar
*data
, int size
, wxIPCFormat format
)
418 if (topic
.IsEmpty() && item
.IsEmpty())
419 s
.Printf(_T("%s("), command
.c_str());
420 else if (topic
.IsEmpty())
421 s
.Printf(_T("%s(item=\"%s\","), command
.c_str(), item
.c_str());
422 else if (item
.IsEmpty())
423 s
.Printf(_T("%s(topic=\"%s\","), command
.c_str(), topic
.c_str());
425 s
.Printf(_T("%s(topic=\"%s\",item=\"%s\","), command
.c_str(), topic
.c_str(), item
.c_str());
427 if (format
== wxIPC_TEXT
|| format
== wxIPC_UNICODETEXT
)
428 wxLogMessage(_T("%s\"%s\",%d)"), s
.c_str(), data
, size
);
429 else if (format
== wxIPC_PRIVATE
)
433 char *bytes
= (char *)data
;
434 wxLogMessage(_T("%s'%c%c%c',%d)"), s
.c_str(), bytes
[0], bytes
[1], bytes
[2], size
);
437 wxLogMessage(_T("%s...,%d)"), s
.c_str(), size
);
439 else if (format
== wxIPC_INVALID
)
440 wxLogMessage(_T("%s[invalid data],%d)"), s
.c_str(), size
);
443 bool MyConnection
::OnAdvise(const wxString
& topic
, const wxString
& item
, wxChar
*data
,
444 int size
, wxIPCFormat format
)
446 Log(_T("OnAdvise"), topic
, item
, data
, size
, format
);
450 bool MyConnection
::OnDisconnect()
452 wxLogMessage(_T("OnDisconnect()"));
453 wxGetApp().GetFrame()->Disconnect();
457 bool MyConnection
::Execute(const wxChar
*data
, int size
, wxIPCFormat format
)
459 Log(_T("Execute"), _T(""), _T(""), (wxChar
*)data
, size
, format
);
460 bool retval
= wxConnection
::Execute(data
, size
, format
);
462 wxLogMessage(_T("Execute failed!"));
466 wxChar
*MyConnection
::Request(const wxString
& item
, int *size
, wxIPCFormat format
)
468 wxChar
*data
= wxConnection
::Request(item
, size
, format
);
469 Log(_T("Request"), _T(""), item
, data
, size ?
*size
: -1, format
);
473 bool MyConnection
::Poke(const wxString
& item
, wxChar
*data
, int size
, wxIPCFormat format
)
475 Log(_T("Poke"), _T(""), item
, data
, size
, format
);
476 return wxConnection
::Poke(item
, data
, size
, format
);