1 //-----------------------------------------------------------------------------
2 // NOTICE:
3 // This version of Snarl Interface is depricated!
4 // Use V41 interface files instead. The files can be found in Snarl SVN:
5 // \trunk\hdr\C++
6 //-----------------------------------------------------------------------------
7
8 //-----------------------------------------------------------------------------
9 // About:
10 // Snarl C++ interface implementation
11 // To understand what the different functions do and what they return, please
12 // have a look at the API on http://www.fullphat.net/dev/api.htm.
13 // Also have a look at mSnarl_i.bas found in the CVS/SVN repository for Snarl.
14 //
15 // The functions in SnarlInterface both have ANSI(UTF8) and UNICODE versions.
16 // If the LPCWSTR (unicode) version of the functions are called, the strings
17 // are converted to UTF8 by SnarlInterface before sent to Snarl. So using the
18 // ANSI/UTF8/LPCSTR versions of the functions are faster!
19 //
20 //
21 // Difference to VB implementation:
22 // Please note that string functions return NULL when they fail and not an
23 // empty string. So check for NULL...
24 // Function names doesn't have the pre "sn".
25 //
26 //
27 // Authors:
28 // Written and maintained by Toke Noer Nøttrup
29 // Original C++ version by "Whitman"
30 //
31 // License etc. :
32 // Feel free to use this code and class as you see fit.
33 // If you improve the code, it would be nice of you to take contact to the
34 // authors, so all can get the benifit.
35 //
36 // There is no guarantee that the code is correct or functional.
37 // USE AT YOUR OWN RISK
38 //-----------------------------------------------------------------------------
39
40 // History
41 // 2010/08/13 : Moved to depricated status - Use the V41 API instead !
42 // 2010/08/02 : Removed some dependencies on safe string functions
43 // : Added uckly casts of HWND to please MinGW64 (since Snarl is 32bit anyway, shouldn't matter.)
44 // 2008/12/31 : Implemented V39 API
45 // : Moved SnarlInterface into new Snarl namespace and moved enums etc. out of class
46 // : Added WCHAR overloads for all functions
47 // 2008/08/27 : Fixed return value of IsMessageVisible and HideMessage (returns false on failure now)
48 // : Fixed critical error in the new overloaded UpdateMessage() function
49 // 2008/08/27 : x64 compiler fix
50 // 2008/08/24 : Renamed all functions to not have prepended "sn".
51 // : Memory allocation functions added. (Use FreeString to free strings returned by Snarl)
52 // : Added m_nLastMessageId to the class. (Use GetLastMessageId() to get it)
53 // : Overloaded a few functions, so one don't have include the message id. (UpdateMessage f.i.)
54
55 // 2008/06/20 : Fixed snShowMessageEx so it actually sends the extended version - oops
56 // : Fixed compiler warning C4800: forcing value to bool 'true' or 'false' (performance warning)
57
58 // 2008/05/19 : uSend and uSendEx would always set return value to M_OK on successfull call
59 // 2008/04/14 : Updated to follow (what should be) the final Snarl 2.0 API
60 // 2008/03/28 : Few fixes for Snarl 2.0
61 // 2007/05/23 : snGetGlobalMsg & snGetSnarlWindow made static
62 // 2007/03/25 : 1.6 RC1 fixup
63 // 2007/03/04 : Added - snGetAppPath, snGetIconsPath, snGetVersionEx,
64 // snSetTimeout, uSendEx
65
66 #define _CRT_SECURE_NO_WARNINGS
67
68 #include "SnarlInterface.h"
69
70 namespace Snarl {
71 namespace V39 {
72
73 //-----------------------------------------------------------------------------
74 // Constructor/Destructor
75 //-----------------------------------------------------------------------------
SnarlInterface()76 SnarlInterface::SnarlInterface()
77 : m_hwndFrom(NULL), m_nLastMessageId(0)
78 {
79
80 }
81
~SnarlInterface()82 SnarlInterface::~SnarlInterface()
83 {
84
85 }
86
87
88 //-----------------------------------------------------------------------------
89 // snShowMessage()
90
91 /// Displays a message with Title and Text. Timeout controls how long the
92 /// message is displayed for (in seconds) (omitting this value means the message
93 /// is displayed indefinately). IconPath specifies the location of a PNG image
94 /// which will be displayed alongside the message text.
95 /// <returns>Message Id on success or M_RESULT on failure</returns>
96
ShowMessage(LPCSTR szTitle,LPCSTR szText,LONG32 timeout,LPCSTR szIconPath,HWND hWndReply,WPARAM uReplyMsg)97 LONG32 SnarlInterface::ShowMessage(LPCSTR szTitle, LPCSTR szText, LONG32 timeout, LPCSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg)
98 {
99 SNARLSTRUCT ss;
100 ZeroMemory((void*)&ss, sizeof(ss));
101
102 ss.Cmd = SNARL_SHOW;
103 strncpy((LPSTR)&ss.Title, szTitle, SNARL_STRING_LENGTH);
104 strncpy((LPSTR)&ss.Text, szText, SNARL_STRING_LENGTH);
105 strncpy((LPSTR)&ss.Icon, szIconPath, SNARL_STRING_LENGTH);
106 ss.Timeout = timeout;
107
108 ss.LngData2 = static_cast<LONG32>(reinterpret_cast<DWORD_PTR>(hWndReply));
109 ss.Id = static_cast<LONG32>(uReplyMsg);
110
111 m_nLastMessageId = Send(ss);
112 return m_nLastMessageId;
113 }
114
ShowMessage(LPCWSTR szTitle,LPCWSTR szText,LONG32 timeout,LPCWSTR szIconPath,HWND hWndReply,WPARAM uReplyMsg)115 LONG32 SnarlInterface::ShowMessage(LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout, LPCWSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg)
116 {
117 LPSTR szUTF8Title = WideToUTF8(szTitle);
118 LPSTR szUTF8Text = WideToUTF8(szText);
119 LPSTR szUFT8IconPath = WideToUTF8(szIconPath);
120
121 LONG32 result = ShowMessage(szUTF8Title, szUTF8Text, timeout, szUFT8IconPath, hWndReply, uReplyMsg);
122
123 delete [] szUTF8Title;
124 delete [] szUTF8Text;
125 delete [] szUFT8IconPath;
126
127 return result;
128 }
129
130 //-----------------------------------------------------------------------------
131 // snShowMessageEx()
132
133 /// Displays a notification. This function is identical to snShowMessage()
134 /// except that Class specifies an alert previously registered with
135 /// snRegisterAlert() and SoundFile can optionally specify a WAV sound to play
136 /// when the notification is displayed on screen.
137
138 /// <returns>Message Id on success or M_RESULT on failure</returns>
139
ShowMessageEx(LPCSTR szClass,LPCSTR szTitle,LPCSTR szText,LONG32 timeout,LPCSTR szIconPath,HWND hWndReply,WPARAM uReplyMsg,LPCSTR szSoundFile)140 LONG32 SnarlInterface::ShowMessageEx(LPCSTR szClass, LPCSTR szTitle, LPCSTR szText, LONG32 timeout, LPCSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg, LPCSTR szSoundFile)
141 {
142 SNARLSTRUCTEX ssex;
143 ZeroMemory((void*)&ssex, sizeof(ssex));
144
145 ssex.Cmd = SNARL_EX_SHOW;
146 ssex.Timeout = timeout;
147 ssex.LngData2 = static_cast<LONG32>(reinterpret_cast<DWORD_PTR>(hWndReply));
148 ssex.Id = static_cast<LONG32>(uReplyMsg);
149
150 strncpy((LPSTR)&ssex.Class, szClass, SNARL_STRING_LENGTH);
151 strncpy((LPSTR)&ssex.Title, szTitle, SNARL_STRING_LENGTH);
152 strncpy((LPSTR)&ssex.Text, szText, SNARL_STRING_LENGTH);
153 strncpy((LPSTR)&ssex.Icon, szIconPath, SNARL_STRING_LENGTH);
154 strncpy((LPSTR)&ssex.Extra, szSoundFile, SNARL_STRING_LENGTH);
155
156 m_nLastMessageId = Send(ssex);
157 return m_nLastMessageId;
158 }
159
ShowMessageEx(LPCWSTR szClass,LPCWSTR szTitle,LPCWSTR szText,LONG32 timeout,LPCWSTR szIconPath,HWND hWndReply,WPARAM uReplyMsg,LPCWSTR szSoundFile)160 LONG32 SnarlInterface::ShowMessageEx(LPCWSTR szClass, LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout, LPCWSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg, LPCWSTR szSoundFile)
161 {
162 LPSTR szUTF8Class = WideToUTF8(szClass);
163 LPSTR szUTF8Title = WideToUTF8(szTitle);
164 LPSTR szUTF8Text = WideToUTF8(szText);
165 LPSTR szUFT8IconPath = WideToUTF8(szIconPath);
166 LPSTR szUFT8SoundFile = WideToUTF8(szSoundFile);
167
168 LONG32 result = ShowMessageEx(szUTF8Class, szUTF8Title, szUTF8Text, timeout, szUFT8IconPath, hWndReply, uReplyMsg, szUFT8SoundFile);
169
170 delete [] szUTF8Class;
171 delete [] szUTF8Title;
172 delete [] szUTF8Text;
173 delete [] szUFT8IconPath;
174 delete [] szUFT8SoundFile;
175
176 return result;
177 }
178
179 //-----------------------------------------------------------------------------
180 // snHideMessage()
181
182 /// Hides the notification specified by Id. Id is the value returned by
183 /// snShowMessage() or snShowMessageEx() when the notification was initially
184 /// created. This function returns True if the notification was successfully
185 /// hidden or False otherwise (for example, the notification may no longer exist).
186
HideMessage(LONG32 Id)187 BOOL SnarlInterface::HideMessage(LONG32 Id)
188 {
189 SNARLSTRUCT ss;
190 ss.Cmd = SNARL_HIDE;
191 ss.Id = Id;
192
193 LONG32 n = Send(ss);
194 return (n == -1 || n == 1) ? TRUE : FALSE;
195 }
196
HideMessage()197 BOOL SnarlInterface::HideMessage()
198 {
199 return HideMessage(m_nLastMessageId);
200 }
201
202 //-----------------------------------------------------------------------------
203 // snIsMessageVisible()
204
205 /// Returns True if the notification specified by Id is still visible, or
206 /// False if not. Id is the value returned by snShowMessage() or
207 /// snShowMessageEx() when the notification was initially created.
208
IsMessageVisible(LONG32 Id)209 BOOL SnarlInterface::IsMessageVisible(LONG32 Id)
210 {
211 SNARLSTRUCT ss;
212 ss.Cmd = SNARL_IS_VISIBLE;
213 ss.Id = Id;
214
215 // We are getting -1 when true, checking for 1 just in case. We don't want to return true for the other M_RESULT returns
216 LONG32 n = Send(ss);
217 return (n == -1 || n == 1) ? TRUE : FALSE;
218 }
219
IsMessageVisible()220 BOOL SnarlInterface::IsMessageVisible()
221 {
222 if (m_nLastMessageId == 0)
223 return FALSE;
224
225 return IsMessageVisible(m_nLastMessageId);
226 }
227
228 //-----------------------------------------------------------------------------
229 // snUpdateMessage()
230
231 /// Changes the title and text in the message specified by Id to the values
232 /// specified by Title and Text respectively. Id is the value returned by
233 /// snShowMessage() or snShowMessageEx() when the notification was originally
234 /// created. To change the timeout parameter of a notification, use snSetTimeout()
235
UpdateMessage(LONG32 id,LPCSTR szTitle,LPCSTR szText,LPCSTR szIconPath)236 M_RESULT SnarlInterface::UpdateMessage(LONG32 id, LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath)
237 {
238 SNARLSTRUCT ss;
239 ZeroMemory((void*)&ss, sizeof(ss));
240
241 ss.Cmd = SNARL_UPDATE;
242 ss.Id = id;
243
244 strncpy((LPSTR)&ss.Title, szTitle, SNARL_STRING_LENGTH);
245 strncpy((LPSTR)&ss.Text, szText, SNARL_STRING_LENGTH);
246 strncpy((LPSTR)&ss.Icon, szIconPath, SNARL_STRING_LENGTH);
247
248 return static_cast<M_RESULT>(Send(ss));
249 }
250
UpdateMessage(LONG32 id,LPCWSTR szTitle,LPCWSTR szText,LPCWSTR szIconPath)251 M_RESULT SnarlInterface::UpdateMessage(LONG32 id, LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath)
252 {
253 LPSTR szParam1 = WideToUTF8(szTitle);
254 LPSTR szParam2 = WideToUTF8(szText);
255 LPSTR szParam3 = WideToUTF8(szIconPath);
256
257 M_RESULT result = UpdateMessage(id, szParam1, szParam2, szParam3);
258
259 delete [] szParam1;
260 delete [] szParam2;
261 delete [] szParam3;
262
263 return result;
264 }
265
UpdateMessage(LPCSTR szTitle,LPCSTR szText,LPCSTR szIconPath)266 M_RESULT SnarlInterface::UpdateMessage(LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath)
267 {
268 return UpdateMessage(m_nLastMessageId, szTitle, szText, szIconPath);
269 }
270
UpdateMessage(LPCWSTR szTitle,LPCWSTR szText,LPCWSTR szIconPath)271 M_RESULT SnarlInterface::UpdateMessage(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath)
272 {
273 return UpdateMessage(m_nLastMessageId, szTitle, szText, szIconPath);
274 }
275
276 //-----------------------------------------------------------------------------
277 // snRegisterConfig
278
279 /// Registers an application's configuration interface with Snarl.
280 /// AppName is the text that's displayed in the Applications list so it should
281 /// be people friendly ("My cool app" rather than "my_cool_app").
282
RegisterConfig(HWND hWnd,LPCSTR szAppName,LONG32 replyMsg)283 M_RESULT SnarlInterface::RegisterConfig(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg)
284 {
285 return RegisterConfig2(hWnd, szAppName, replyMsg, "");
286 }
287
RegisterConfig(HWND hWnd,LPCWSTR szAppName,LONG32 replyMsg)288 M_RESULT SnarlInterface::RegisterConfig(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg)
289 {
290 return RegisterConfig2(hWnd, szAppName, replyMsg, L"");
291 }
292
293 //-----------------------------------------------------------------------------
294 // snRegisterConfig2
295
296 /// Registers an application's configuration interface with Snarl.
297 /// This function is identical to snRegisterConfig() except that Icon can be
298 /// used to specify a PNG image which will be displayed against the
299 /// application's entry in Snarl's Preferences panel.
300
RegisterConfig2(HWND hWnd,LPCSTR szAppName,LONG32 replyMsg,LPCSTR szIcon)301 M_RESULT SnarlInterface::RegisterConfig2(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg, LPCSTR szIcon)
302 {
303 if (!szAppName || !szIcon)
304 return M_BAD_POINTER;
305
306 SNARLSTRUCT ss;
307
308 m_hwndFrom = hWnd;
309
310 ss.Cmd = SNARL_REGISTER_CONFIG_WINDOW_2;
311 ss.LngData2 = static_cast<LONG32>(reinterpret_cast<DWORD_PTR>(hWnd));
312 ss.Id = replyMsg;
313 strncpy((LPSTR)&ss.Title, szAppName, SNARL_STRING_LENGTH);
314 strncpy((LPSTR)&ss.Icon, szIcon, SNARL_STRING_LENGTH);
315
316 return static_cast<M_RESULT>(Send(ss));
317 }
318
RegisterConfig2(HWND hWnd,LPCWSTR szAppName,LONG32 replyMsg,LPCWSTR szIcon)319 M_RESULT SnarlInterface::RegisterConfig2(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg, LPCWSTR szIcon)
320 {
321 LPSTR szParam1 = WideToUTF8(szAppName);
322 LPSTR szParam2 = WideToUTF8(szIcon);
323
324 M_RESULT result = RegisterConfig2(hWnd, szParam1, replyMsg, szParam2);
325
326 delete [] szParam1;
327 delete [] szParam2;
328
329 return result;
330 }
331
332
333 //-----------------------------------------------------------------------------
334 // snRevokeConfig
335
336 /// Removes the application previously registered using snRegisterConfig() or
337 /// snRegisterConfig2(). hWnd should be the same as that used during registration.
338
RevokeConfig(HWND hWnd)339 M_RESULT SnarlInterface::RevokeConfig(HWND hWnd)
340 {
341 SNARLSTRUCT ss;
342
343 m_hwndFrom = NULL;
344
345 ss.Cmd = SNARL_REVOKE_CONFIG_WINDOW;
346 ss.LngData2 = static_cast<LONG32>(reinterpret_cast<DWORD_PTR>(hWnd));
347
348 return static_cast<M_RESULT>(Send(ss));
349 }
350
351
352 //-----------------------------------------------------------------------------
353 // snGetVersion()
354
355 /// Checks if Snarl is currently running and, if it is, retrieves the major and
356 /// minor release version numbers in Major and Minor respectively.
357 /// Returns True if Snarl is running, False otherwise.
358
GetVersion(WORD * Major,WORD * Minor)359 BOOL SnarlInterface::GetVersion(WORD* Major, WORD* Minor)
360 {
361 SNARLSTRUCT ss;
362 ss.Cmd = SNARL_GET_VERSION;
363 LONG32 versionInfo = Send(ss);
364 if (versionInfo > 0 && versionInfo != M_FAILED && versionInfo != M_TIMED_OUT) {
365 *Major = HIWORD(versionInfo);
366 *Minor = LOWORD(versionInfo);
367 return TRUE;
368 }
369 return FALSE;
370 }
371
372
373 //-----------------------------------------------------------------------------
374 // snGetVersionEx
375
376 /// Returns the Snarl system version number. This is an integer value which
377 /// represents the system build number and can be used to identify the specific
378 /// version of Snarl running
379
GetVersionEx()380 LONG32 SnarlInterface::GetVersionEx()
381 {
382 SNARLSTRUCT ss;
383 ss.Cmd = SNARL_GET_VERSION_EX;
384 return Send(ss);
385 }
386
387
388 //-----------------------------------------------------------------------------
389 // snSetTimeout()
390
391 /// Sets the timeout of existing notification Id to Timeout seconds. Id is the
392 /// value returned by snShowMessage() or snShowMessageEx() when the notification
393 /// was first created.
394
SetTimeout(LONG32 Id,LONG32 Timeout)395 M_RESULT SnarlInterface::SetTimeout(LONG32 Id, LONG32 Timeout)
396 {
397 SNARLSTRUCT ss;
398 ss.Cmd = SNARL_SET_TIMEOUT;
399 ss.Id = Id;
400 ss.LngData2 = Timeout;
401
402 return static_cast<M_RESULT>(Send(ss));
403 }
404
SetTimeout(LONG32 Timeout)405 M_RESULT SnarlInterface::SetTimeout(LONG32 Timeout)
406 {
407 return SetTimeout(m_nLastMessageId, Timeout);
408 }
409
410 //-----------------------------------------------------------------------------
411 // snRegisterAlert()
412
413 /// Registers an alert of Class for application AppName which must have previously
414 /// been registered with either snRegisterConfig() or snRegisterConfig2().
415
RegisterAlert(LPCSTR szAppName,LPCSTR szClass)416 M_RESULT SnarlInterface::RegisterAlert(LPCSTR szAppName, LPCSTR szClass)
417 {
418 SNARLSTRUCT ss;
419 ss.Cmd = SNARL_REGISTER_ALERT;
420 strncpy((LPSTR)&ss.Title, szAppName, SNARL_STRING_LENGTH);
421 strncpy((LPSTR)&ss.Text, szClass, SNARL_STRING_LENGTH);
422
423 return static_cast<M_RESULT>(Send(ss));
424 }
425
RegisterAlert(LPCWSTR szAppName,LPCWSTR szClass)426 M_RESULT SnarlInterface::RegisterAlert(LPCWSTR szAppName, LPCWSTR szClass)
427 {
428 LPSTR szParam1 = WideToUTF8(szAppName);
429 LPSTR szParam2 = WideToUTF8(szClass);
430
431 M_RESULT result = RegisterAlert(szParam1, szParam2);
432
433 delete [] szParam1;
434 delete [] szParam2;
435
436 return result;
437 }
438
439 //-----------------------------------------------------------------------------
440 // snGetGlobalMsg()
441
442 /// Returns the atom that corresponds to the "SnarlGlobalEvent" registered
443 /// Windows message. This message is sent by Snarl when it is first starts and
444 /// when it shuts down.
445
GetGlobalMsg()446 LONG32 SnarlInterface::GetGlobalMsg()
447 {
448 return RegisterWindowMessage(SNARL_GLOBAL_MSG);
449 }
450
451
452 //-----------------------------------------------------------------------------
453 // snGetSnarlWindow
454
GetSnarlWindow()455 HWND SnarlInterface::GetSnarlWindow()
456 {
457 HWND hWnd = FindWindow(SNARL_WINDOW_CLASS, SNARL_WINDOW_TITLE);
458 if (hWnd == NULL)
459 hWnd = FindWindow(NULL, SNARL_WINDOW_TITLE);
460
461 return hWnd;
462 }
463
464
465 //-----------------------------------------------------------------------------
466 // snGetAppPath()
467
468 /// Returns a pointer to the path.
469 /// ** Remember to call FreeString
470
GetAppPath()471 LPCTSTR SnarlInterface::GetAppPath()
472 {
473 HWND hWnd = GetSnarlWindow();
474 if (hWnd)
475 {
476 HWND hWndPath = FindWindowEx(hWnd, NULL, _T("static"), NULL);
477 if (hWndPath)
478 {
479 TCHAR strTmp[MAX_PATH] = {0};
480 int nReturn = GetWindowText(hWndPath, strTmp, MAX_PATH-1);
481 if (nReturn > 0) {
482 TCHAR* strReturn = AllocateString(nReturn + 1);
483 _tcsncpy(strReturn, strTmp, nReturn + 1);
484 strReturn[nReturn] = 0;
485 return strReturn;
486 }
487 }
488 }
489
490 return NULL;
491 }
492
493
494 //-----------------------------------------------------------------------------
495 // snGetIconsPath()
496
497 /// Returns a pointer to the iconpath.
498 /// ** Remember to call FreeString when done with the string
499
GetIconsPath()500 LPCTSTR SnarlInterface::GetIconsPath()
501 {
502 TCHAR* szIconPath = NULL;
503 LPCTSTR szPath = GetAppPath();
504 if (!szPath)
505 return NULL;
506
507 size_t nLen = 0;
508 // TODO: _tcsnlen MAX_PATH
509 if (nLen = _tcslen(szPath))
510 {
511 nLen += 10 + 1; // etc\\icons\\ + NULL
512 szIconPath = AllocateString(nLen);
513
514 _tcsncpy(szIconPath, szPath, nLen);
515 _tcsncat(szIconPath, _T("etc\\icons\\"), nLen);
516 }
517
518 FreeString(szPath);
519
520 return szIconPath;
521 }
522
523
524 //-----------------------------------------------------------------------------
525 // snSetAsSnarlApp()
526
527 /// Identifies an application as a Snarl App. (V39)
528
SetAsSnarlApp(HWND hWndOwner,SNARL_APP_FLAGS Flags)529 void SnarlInterface::SetAsSnarlApp(HWND hWndOwner, SNARL_APP_FLAGS Flags)
530 {
531 if (IsWindow(hWndOwner)) {
532 SetProp(hWndOwner, _T("snarl_app"), reinterpret_cast<HANDLE>(1));
533 SetProp(hWndOwner, _T("snarl_app_flags"), reinterpret_cast<HANDLE>(Flags));
534 }
535 }
536
537
538 //-----------------------------------------------------------------------------
539 // snGetAppMsg()
540
541 /// Returns the global Snarl Application message (V39)
542
GetAppMsg()543 LONG32 SnarlInterface::GetAppMsg()
544 {
545 return RegisterWindowMessage(SNARL_APP_MSG);
546 }
547
548
549 //-----------------------------------------------------------------------------
550 // snRegisterApp()
551
552 /// Registers an application with Snarl (V39)
553
RegisterApp(LPCSTR Application,LPCSTR SmallIcon,LPCSTR LargeIcon,HWND hWnd,LONG32 ReplyMsg)554 M_RESULT SnarlInterface::RegisterApp(LPCSTR Application, LPCSTR SmallIcon, LPCSTR LargeIcon, HWND hWnd, LONG32 ReplyMsg)
555 {
556 m_hwndFrom = hWnd;
557
558 SNARLSTRUCT ss;
559 ss.Cmd = SNARL_REGISTER_APP;
560
561 strncpy((LPSTR)&ss.Title, Application, SNARL_STRING_LENGTH);
562 strncpy((LPSTR)&ss.Icon, SmallIcon, SNARL_STRING_LENGTH);
563 strncpy((LPSTR)&ss.Text, LargeIcon, SNARL_STRING_LENGTH);
564
565 ss.LngData2 = static_cast<LONG32>(reinterpret_cast<DWORD_PTR>(hWnd));
566 ss.Id = ReplyMsg;
567 ss.Timeout = GetCurrentProcessId();
568
569 return static_cast<M_RESULT>(Send(ss));
570 }
571
RegisterApp(LPCWSTR Application,LPCWSTR SmallIcon,LPCWSTR LargeIcon,HWND hWnd,LONG32 ReplyMsg)572 M_RESULT SnarlInterface::RegisterApp(LPCWSTR Application, LPCWSTR SmallIcon, LPCWSTR LargeIcon, HWND hWnd, LONG32 ReplyMsg)
573 {
574 LPSTR szParam1 = WideToUTF8(Application);
575 LPSTR szParam2 = WideToUTF8(SmallIcon);
576 LPSTR szParam3 = WideToUTF8(LargeIcon);
577
578 M_RESULT result = RegisterApp(szParam1, szParam2, szParam3, hWnd, ReplyMsg);
579
580 delete [] szParam1;
581 delete [] szParam2;
582 delete [] szParam3;
583
584 return result;
585 }
586
587
588 //-----------------------------------------------------------------------------
589 // snUnregisterApp()
590
591 /// Unregisters an application with Snarl (V39)
592
UnregisterApp()593 M_RESULT SnarlInterface::UnregisterApp()
594 {
595 SNARLSTRUCT ss;
596 ss.Cmd = SNARL_UNREGISTER_APP;
597 ss.LngData2 = GetCurrentProcessId();
598
599 m_hwndFrom = NULL;
600
601 return static_cast<M_RESULT>(Send(ss));
602 }
603
604
605 //-----------------------------------------------------------------------------
606 // snShowNotification()
607
608 /// Displays a Snarl notification using registered class (V39)
609 /// <returns>Message Id on success or M_RESULT on failure</returns>
610 /// LPCSTR Icon = NULL, HWND hWndReply = NULL, LONG32 uReplyMsg = 0, LPCSTR Sound = NULL);
ShowNotification(LPCSTR Class,LPCSTR Title,LPCSTR Text,LONG32 Timeout,LPCSTR Icon,HWND hWndReply,LONG32 uReplyMsg,LPCSTR Sound)611 LONG32 SnarlInterface::ShowNotification(LPCSTR Class, LPCSTR Title, LPCSTR Text, LONG32 Timeout, LPCSTR Icon /* = NULL */, HWND hWndReply /* = NULL */, LONG32 uReplyMsg /* = 0 */, LPCSTR Sound /* = NULL */)
612 {
613 SNARLSTRUCTEX ssex;
614 ZeroMemory(&ssex, sizeof(SNARLSTRUCTEX));
615
616 ssex.Cmd = SNARL_SHOW_NOTIFICATION;
617
618 strncpy((LPSTR)&ssex.Title, Title, SNARL_STRING_LENGTH);
619 strncpy((LPSTR)&ssex.Text, Text, SNARL_STRING_LENGTH);
620 if (Icon != NULL)
621 strncpy((LPSTR)&ssex.Icon, Icon, SNARL_STRING_LENGTH);
622 if (Sound != NULL)
623 strncpy((LPSTR)&ssex.Extra, Sound, SNARL_STRING_LENGTH);
624 if (Class != NULL)
625 strncpy((LPSTR)&ssex.Class, Class, SNARL_STRING_LENGTH);
626
627 ssex.Timeout = Timeout;
628 ssex.LngData2 = static_cast<LONG32>(reinterpret_cast<DWORD_PTR>(hWndReply));
629 ssex.Id = uReplyMsg;
630 ssex.Reserved1 = GetCurrentProcessId();
631
632 m_nLastMessageId = Send(ssex);
633 return m_nLastMessageId;
634 }
635
ShowNotification(LPCWSTR Class,LPCWSTR Title,LPCWSTR Text,LONG32 Timeout,LPCWSTR Icon,HWND hWndReply,LONG32 uReplyMsg,LPCWSTR Sound)636 LONG32 SnarlInterface::ShowNotification(LPCWSTR Class, LPCWSTR Title, LPCWSTR Text, LONG32 Timeout, LPCWSTR Icon, HWND hWndReply, LONG32 uReplyMsg, LPCWSTR Sound)
637 {
638 LPSTR szParam1 = WideToUTF8(Class);
639 LPSTR szParam2 = WideToUTF8(Title);
640 LPSTR szParam3 = WideToUTF8(Text);
641 LPSTR szParam4 = WideToUTF8(Icon);
642 LPSTR szParam5 = WideToUTF8(Sound);
643
644 LONG32 result = ShowNotification(szParam1, szParam2, szParam3, Timeout, szParam4, hWndReply, uReplyMsg, szParam5);
645
646 delete [] szParam1;
647 delete [] szParam2;
648 delete [] szParam3;
649 delete [] szParam4;
650 delete [] szParam5;
651
652 return result;
653 }
654
655
656 //-----------------------------------------------------------------------------
657 // snChangeAttribute()
658
659 /// (V39)
660
ChangeAttribute(LONG32 Id,SNARL_ATTRIBUTES Attr,LPCSTR Value)661 M_RESULT SnarlInterface::ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCSTR Value)
662 {
663 SNARLSTRUCT ss;
664 ss.Cmd = SNARL_CHANGE_ATTR;
665 ss.Id = Id;
666 ss.LngData2 = Attr;
667
668 strncpy((LPSTR)&ss.Text, Value, SNARL_STRING_LENGTH);
669
670 return static_cast<M_RESULT>(Send(ss));
671 }
672
ChangeAttribute(LONG32 Id,SNARL_ATTRIBUTES Attr,LPCWSTR Value)673 M_RESULT SnarlInterface::ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCWSTR Value)
674 {
675 LPSTR szParam1 = WideToUTF8(Value);
676
677 M_RESULT result = ChangeAttribute(Id, Attr, szParam1);
678
679 delete [] szParam1;
680
681 return result;
682 }
683
ChangeAttribute(SNARL_ATTRIBUTES Attr,LPCSTR Value)684 M_RESULT SnarlInterface::ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCSTR Value)
685 {
686 return ChangeAttribute(m_nLastMessageId, Attr, Value);
687 }
688
ChangeAttribute(SNARL_ATTRIBUTES Attr,LPCWSTR Value)689 M_RESULT SnarlInterface::ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCWSTR Value)
690 {
691 return ChangeAttribute(m_nLastMessageId, Attr, Value);
692 }
693
694
695 //-----------------------------------------------------------------------------
696 // snSetClassDefault()
697
698 /// Sets the default value for an alert class (V39)
699
SetClassDefault(LPCSTR Class,SNARL_ATTRIBUTES Attr,LPCSTR Value)700 M_RESULT SnarlInterface::SetClassDefault(LPCSTR Class, SNARL_ATTRIBUTES Attr, LPCSTR Value)
701 {
702 SNARLSTRUCT ss;
703 ss.Cmd = SNARL_SET_CLASS_DEFAULT;
704 ss.LngData2 = Attr;
705 ss.Timeout = GetCurrentProcessId();
706
707 strncpy((LPSTR)&ss.Text, Class, SNARL_STRING_LENGTH);
708 strncpy((LPSTR)&ss.Icon, Value, SNARL_STRING_LENGTH);
709
710 return static_cast<M_RESULT>(Send(ss));
711 }
712
SetClassDefault(LPCWSTR Class,SNARL_ATTRIBUTES Attr,LPCWSTR Value)713 M_RESULT SnarlInterface::SetClassDefault(LPCWSTR Class, SNARL_ATTRIBUTES Attr, LPCWSTR Value)
714 {
715 LPSTR szParam1 = WideToUTF8(Class);
716 LPSTR szParam2 = WideToUTF8(Value);
717
718 M_RESULT result = SetClassDefault(szParam1, Attr, szParam2);
719
720 delete [] szParam1;
721 delete [] szParam2;
722
723 return result;
724 }
725
726
727 //-----------------------------------------------------------------------------
728 // snGetRevision()
729
730 /// Gets the current Snarl revision (build) number (V39)
731 /// Returns the build version number, or M_RESULT on failure.
732
GetRevision()733 LONG32 SnarlInterface::GetRevision()
734 {
735 SNARLSTRUCT ss;
736 ss.Cmd = SNARL_GET_REVISION;
737 ss.LngData2 = 0xFFFE;
738
739 return Send(ss);
740 }
741
742
743 //-----------------------------------------------------------------------------
744 // snAddClass()
745
746 /// (V39)
747
AddClass(LPCSTR Class,LPCSTR Description,SNARL_CLASS_FLAGS Flags,LPCSTR DefaultTitle,LPCSTR DefaultIcon,LONG32 DefaultTimeout)748 M_RESULT SnarlInterface::AddClass(LPCSTR Class, LPCSTR Description, SNARL_CLASS_FLAGS Flags, LPCSTR DefaultTitle, LPCSTR DefaultIcon, LONG32 DefaultTimeout)
749 {
750 SNARLSTRUCT ss;
751 ss.Cmd = SNARL_ADD_CLASS;
752 ss.LngData2 = Flags;
753 ss.Timeout = GetCurrentProcessId();
754
755 strncpy((LPSTR)&ss.Text, Class, SNARL_STRING_LENGTH);
756 strncpy((LPSTR)&ss.Title, Description, SNARL_STRING_LENGTH);
757
758 LONG32 result = Send(ss);
759
760 if (static_cast<M_RESULT>(result) == M_OK)
761 {
762 SetClassDefault(Class, SNARL_ATTRIBUTE_TITLE, DefaultTitle);
763 SetClassDefault(Class, SNARL_ATTRIBUTE_ICON, DefaultIcon);
764 if (DefaultTimeout > 0) {
765 char str[64] = {0};
766 _snprintf((LPSTR)&str, sizeof(str), "%d", DefaultTimeout);
767 SetClassDefault(Class, SNARL_ATTRIBUTE_TIMEOUT, str);
768 }
769
770 return M_OK;
771 }
772 else
773 return M_FAILED;
774 }
775
AddClass(LPCWSTR Class,LPCWSTR Description,SNARL_CLASS_FLAGS Flags,LPCWSTR DefaultTitle,LPCWSTR DefaultIcon,LONG32 DefaultTimeout)776 M_RESULT SnarlInterface::AddClass(LPCWSTR Class, LPCWSTR Description, SNARL_CLASS_FLAGS Flags, LPCWSTR DefaultTitle, LPCWSTR DefaultIcon, LONG32 DefaultTimeout)
777 {
778 LPCSTR szClass = WideToUTF8(Class);
779 LPCSTR szDescription = WideToUTF8(Description);
780 LPCSTR szDefaultTitle = WideToUTF8(DefaultTitle);
781 LPCSTR szDefaultIcon = WideToUTF8(DefaultIcon);
782
783 M_RESULT result = AddClass(szClass, szDescription, Flags, szDefaultTitle, szDefaultIcon, DefaultTimeout);
784
785 delete [] szClass;
786 delete [] szDescription;
787 delete [] szDefaultTitle;
788 delete [] szDefaultIcon;
789
790 return result;
791 }
792
793 //-----------------------------------------------------------------------------
794 // Private functions
795 //-----------------------------------------------------------------------------
796
797 template <class T>
Send(T ss)798 LONG32 SnarlInterface::Send(T ss)
799 {
800 DWORD_PTR nReturn = M_FAILED;
801
802 HWND hWnd = GetSnarlWindow();
803 if (IsWindow(hWnd))
804 {
805 COPYDATASTRUCT cds;
806 cds.dwData = 2;
807 cds.cbData = sizeof(ss);
808 cds.lpData = &ss;
809
810 if (SendMessageTimeout(hWnd, WM_COPYDATA, (WPARAM)m_hwndFrom, (LPARAM)&cds, SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000, &nReturn) == 0)
811 {
812 if (GetLastError() == ERROR_TIMEOUT)
813 nReturn = M_TIMED_OUT;
814 }
815 }
816
817 return static_cast<LONG32>(nReturn);
818 }
819
820 //-----------------------------------------------------------------------------
821
822 // Remember to : delete [] returned string
823
WideToUTF8(LPCWSTR szWideStr)824 LPSTR SnarlInterface::WideToUTF8(LPCWSTR szWideStr)
825 {
826 if (szWideStr == NULL)
827 return NULL;
828
829 int nSize = WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, NULL, 0, NULL, NULL);
830 LPSTR szUTF8 = new char[nSize];
831 WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, szUTF8, nSize, NULL, NULL);
832
833 return szUTF8;
834 }
835
836 }
837 } // namespace Snarl::V39
838