Misc.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554
  1. #include "stdafx.h"
  2. #include "CP_Main.h"
  3. #include "Misc.h"
  4. #include "OptionsSheet.h"
  5. #include "TextConvert.h"
  6. #include "AlphaBlend.h"
  7. #include "Tlhelp32.h"
  8. // Debug Functions
  9. CString GetIPAddress()
  10. {
  11. WORD wVersionRequested;
  12. WSADATA wsaData;
  13. char name[255];
  14. CString IP;
  15. PHOSTENT hostinfo;
  16. wVersionRequested = MAKEWORD(2,0);
  17. if (WSAStartup(wVersionRequested, &wsaData)==0)
  18. {
  19. if(gethostname(name, sizeof(name))==0)
  20. {
  21. if((hostinfo=gethostbyname(name)) != NULL)
  22. {
  23. IP = inet_ntoa(*(struct in_addr*)* hostinfo->h_addr_list);
  24. }
  25. }
  26. WSACleanup();
  27. }
  28. IP.MakeUpper();
  29. return IP;
  30. }
  31. CString GetComputerName()
  32. {
  33. TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH+1] = _T("");
  34. DWORD Size=MAX_COMPUTERNAME_LENGTH+1;
  35. GetComputerName(ComputerName, &Size);
  36. CString cs(ComputerName);
  37. cs.MakeUpper();
  38. return cs;
  39. }
  40. void AppendToFile(const TCHAR* fn, const TCHAR* msg)
  41. {
  42. #ifdef _UNICODE
  43. FILE *file = _wfopen(fn, _T("a"));
  44. #else
  45. FILE *file = fopen(fn, _T("a"));
  46. #endif
  47. ASSERT( file );
  48. #ifdef _UNICODE
  49. fwprintf(file, msg);
  50. #else
  51. fprintf(file, msg);
  52. #endif
  53. fclose(file);
  54. }
  55. void log(const TCHAR* msg, bool bFromSendRecieve, CString csFile, long lLine)
  56. {
  57. ASSERT(AfxIsValidString(msg));
  58. CTime time = CTime::GetCurrentTime();
  59. CString csText = time.Format("[%Y/%m/%d %I:%M:%S %p - ");
  60. CString csFileLine;
  61. csFile = GetFileName(csFile);
  62. csFileLine.Format(_T("%s %d] "), csFile, lLine);
  63. csText += csFileLine;
  64. csText += msg;
  65. csText += "\n";
  66. #ifndef _DEBUG
  67. if(CGetSetOptions::m_bOutputDebugString)
  68. #endif
  69. {
  70. OutputDebugString(csText);
  71. }
  72. #ifndef _DEBUG
  73. if(!bFromSendRecieve)
  74. {
  75. if(!g_Opt.m_bEnableDebugLogging)
  76. return;
  77. }
  78. #endif
  79. CString csExeFile = CGetSetOptions::GetPath(PATH_LOG_FILE);
  80. csExeFile += "Ditto.log";
  81. AppendToFile(csExeFile, csText);
  82. }
  83. void logsendrecieveinfo(CString cs, CString csFile, long lLine)
  84. {
  85. if(g_Opt.m_bLogSendReceiveErrors)
  86. log(cs, true, csFile, lLine);
  87. }
  88. CString GetErrorString( int err )
  89. {
  90. CString str;
  91. LPVOID lpMsgBuf;
  92. ::FormatMessage(
  93. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  94. NULL,
  95. err,
  96. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  97. (LPTSTR) &lpMsgBuf,
  98. 0,
  99. NULL
  100. );
  101. str = (LPCTSTR) lpMsgBuf;
  102. // Display the string.
  103. // ::MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
  104. ::LocalFree( lpMsgBuf );
  105. return str;
  106. }
  107. // Utility Functions
  108. CString StrF(const TCHAR * pszFormat, ...)
  109. {
  110. ASSERT( AfxIsValidString( pszFormat ) );
  111. CString str;
  112. va_list argList;
  113. va_start( argList, pszFormat );
  114. str.FormatV( pszFormat, argList );
  115. va_end( argList );
  116. return str;
  117. }
  118. BYTE GetEscapeChar( BYTE ch )
  119. {
  120. switch(ch)
  121. {
  122. case '\'': return '\''; // Single quotation mark (') = 39 or 0x27
  123. case '\"': return '\"'; // Double quotation mark (") = 34 or 0x22
  124. case '?': return '\?'; // Question mark (?) = 63 or 0x3f
  125. case '\\': return '\\'; // Backslash (\) = 92 or 0x5c
  126. case 'a': return '\a'; // Alert (BEL) = 7
  127. case 'b': return '\b'; // Backspace (BS) = 8
  128. case 'f': return '\f'; // Formfeed (FF) = 12 or 0x0c
  129. case 'n': return '\n'; // Newline (NL or LF) = 10 or 0x0a
  130. case 'r': return '\r'; // Carriage Return (CR) = 13 or 0x0d
  131. case 't': return '\t'; // Horizontal tab (HT) = 9
  132. case 'v': return '\v'; // Vertical tab (VT) = 11 or 0x0b
  133. case '0': return '\0'; // Null character (NUL) = 0
  134. }
  135. return 0; // invalid
  136. }
  137. CString RemoveEscapes( const TCHAR* str )
  138. {
  139. ASSERT( str );
  140. CString ret;
  141. TCHAR* pSrc = (TCHAR*) str;
  142. TCHAR* pDest = ret.GetBuffer(STRLEN(pSrc));
  143. TCHAR* pStart = pDest;
  144. while( *pSrc != '\0' )
  145. {
  146. if( *pSrc == '\\' )
  147. {
  148. pSrc++;
  149. *pDest = GetEscapeChar((BYTE)pSrc );
  150. }
  151. else
  152. *pDest = *pSrc;
  153. pSrc++;
  154. pDest++;
  155. }
  156. ret.ReleaseBuffer( pDest - pStart );
  157. return ret;
  158. }
  159. CString GetWndText( HWND hWnd )
  160. {
  161. CString text;
  162. if( !IsWindow(hWnd) )
  163. return "! NOT A VALID WINDOW !";
  164. CWnd* pWnd = CWnd::FromHandle(hWnd);
  165. pWnd->GetWindowText(text);
  166. return text;
  167. }
  168. bool IsAppWnd( HWND hWnd )
  169. {
  170. DWORD dwMyPID = ::GetCurrentProcessId();
  171. DWORD dwTestPID;
  172. ::GetWindowThreadProcessId( hWnd, &dwTestPID );
  173. return dwMyPID == dwTestPID;
  174. }
  175. /*----------------------------------------------------------------------------*\
  176. Global Memory Helper Functions
  177. \*----------------------------------------------------------------------------*/
  178. // make sure the given HGLOBAL is valid.
  179. BOOL IsValid( HGLOBAL hGlobal )
  180. {
  181. void* pvData = ::GlobalLock( hGlobal );
  182. ::GlobalUnlock( hGlobal );
  183. return ( pvData != NULL );
  184. }
  185. // asserts if hDest isn't big enough
  186. void CopyToGlobalHP( HGLOBAL hDest, LPVOID pBuf, ULONG ulBufLen )
  187. {
  188. ASSERT( hDest && pBuf && ulBufLen );
  189. LPVOID pvData = GlobalLock(hDest);
  190. ASSERT( pvData );
  191. ULONG size = GlobalSize(hDest);
  192. ASSERT( size >= ulBufLen ); // assert if hDest isn't big enough
  193. memcpy(pvData, pBuf, ulBufLen);
  194. GlobalUnlock(hDest);
  195. }
  196. void CopyToGlobalHH( HGLOBAL hDest, HGLOBAL hSource, ULONG ulBufLen )
  197. {
  198. ASSERT( hDest && hSource && ulBufLen );
  199. LPVOID pvData = GlobalLock(hSource);
  200. ASSERT( pvData );
  201. ULONG size = GlobalSize(hSource);
  202. ASSERT( size >= ulBufLen ); // assert if hSource isn't big enough
  203. CopyToGlobalHP(hDest, pvData, ulBufLen);
  204. GlobalUnlock(hSource);
  205. }
  206. HGLOBAL NewGlobalP( LPVOID pBuf, UINT nLen )
  207. {
  208. ASSERT( pBuf && nLen );
  209. HGLOBAL hDest = GlobalAlloc( GMEM_MOVEABLE | GMEM_SHARE, nLen );
  210. ASSERT( hDest );
  211. CopyToGlobalHP( hDest, pBuf, nLen );
  212. return hDest;
  213. }
  214. HGLOBAL NewGlobal(UINT nLen)
  215. {
  216. ASSERT(nLen);
  217. HGLOBAL hDest = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, nLen);
  218. return hDest;
  219. }
  220. HGLOBAL NewGlobalH( HGLOBAL hSource, UINT nLen )
  221. {
  222. ASSERT( hSource && nLen );
  223. LPVOID pvData = GlobalLock( hSource );
  224. HGLOBAL hDest = NewGlobalP( pvData, nLen );
  225. GlobalUnlock( hSource );
  226. return hDest;
  227. }
  228. int CompareGlobalHP(HGLOBAL hLeft, LPVOID pBuf, ULONG ulBufLen)
  229. {
  230. ASSERT(hLeft && pBuf && ulBufLen);
  231. LPVOID pvData = GlobalLock(hLeft);
  232. ASSERT(pvData);
  233. ASSERT(ulBufLen <= GlobalSize(hLeft));
  234. int result = memcmp(pvData, pBuf, ulBufLen);
  235. GlobalUnlock(hLeft);
  236. return result;
  237. }
  238. int CompareGlobalHH( HGLOBAL hLeft, HGLOBAL hRight, ULONG ulBufLen )
  239. {
  240. ASSERT( hLeft && hRight && ulBufLen );
  241. ASSERT( ulBufLen <= GlobalSize(hRight) );
  242. LPVOID pvData = GlobalLock(hRight);
  243. ASSERT( pvData );
  244. int result = CompareGlobalHP( hLeft, pvData, ulBufLen );
  245. GlobalUnlock( hLeft );
  246. return result;
  247. }
  248. //Do not change these these are stored in the database
  249. CLIPFORMAT GetFormatID(LPCTSTR cbName)
  250. {
  251. if(STRCMP(cbName, _T("CF_TEXT")) == 0)
  252. return CF_TEXT;
  253. else if(STRCMP(cbName, _T("CF_METAFILEPICT")) == 0)
  254. return CF_METAFILEPICT;
  255. else if(STRCMP(cbName, _T("CF_SYLK")) == 0)
  256. return CF_SYLK;
  257. else if(STRCMP(cbName, _T("CF_DIF")) == 0)
  258. return CF_DIF;
  259. else if(STRCMP(cbName, _T("CF_TIFF")) == 0)
  260. return CF_TIFF;
  261. else if(STRCMP(cbName, _T("CF_OEMTEXT")) == 0)
  262. return CF_OEMTEXT;
  263. else if(STRCMP(cbName, _T("CF_DIB")) == 0)
  264. return CF_DIB;
  265. else if(STRCMP(cbName, _T("CF_PALETTE")) == 0)
  266. return CF_PALETTE;
  267. else if(STRCMP(cbName, _T("CF_PENDATA")) == 0)
  268. return CF_PENDATA;
  269. else if(STRCMP(cbName, _T("CF_RIFF")) == 0)
  270. return CF_RIFF;
  271. else if(STRCMP(cbName, _T("CF_WAVE")) == 0)
  272. return CF_WAVE;
  273. else if(STRCMP(cbName, _T("CF_UNICODETEXT")) == 0)
  274. return CF_UNICODETEXT;
  275. else if(STRCMP(cbName, _T("CF_ENHMETAFILE")) == 0)
  276. return CF_ENHMETAFILE;
  277. else if(STRCMP(cbName, _T("CF_HDROP")) == 0)
  278. return CF_HDROP;
  279. else if(STRCMP(cbName, _T("CF_LOCALE")) == 0)
  280. return CF_LOCALE;
  281. else if(STRCMP(cbName, _T("CF_OWNERDISPLAY")) == 0)
  282. return CF_OWNERDISPLAY;
  283. else if(STRCMP(cbName, _T("CF_DSPTEXT")) == 0)
  284. return CF_DSPTEXT;
  285. else if(STRCMP(cbName, _T("CF_DSPBITMAP")) == 0)
  286. return CF_DSPBITMAP;
  287. else if(STRCMP(cbName, _T("CF_DSPMETAFILEPICT")) == 0)
  288. return CF_DSPMETAFILEPICT;
  289. else if(STRCMP(cbName, _T("CF_DSPENHMETAFILE")) == 0)
  290. return CF_DSPENHMETAFILE;
  291. return ::RegisterClipboardFormat(cbName);
  292. }
  293. //Do not change these these are stored in the database
  294. CString GetFormatName(CLIPFORMAT cbType)
  295. {
  296. switch(cbType)
  297. {
  298. case CF_TEXT:
  299. return _T("CF_TEXT");
  300. case CF_BITMAP:
  301. return _T("CF_BITMAP");
  302. case CF_METAFILEPICT:
  303. return _T("CF_METAFILEPICT");
  304. case CF_SYLK:
  305. return _T("CF_SYLK");
  306. case CF_DIF:
  307. return _T("CF_DIF");
  308. case CF_TIFF:
  309. return _T("CF_TIFF");
  310. case CF_OEMTEXT:
  311. return _T("CF_OEMTEXT");
  312. case CF_DIB:
  313. return _T("CF_DIB");
  314. case CF_PALETTE:
  315. return _T("CF_PALETTE");
  316. case CF_PENDATA:
  317. return _T("CF_PENDATA");
  318. case CF_RIFF:
  319. return _T("CF_RIFF");
  320. case CF_WAVE:
  321. return _T("CF_WAVE");
  322. case CF_UNICODETEXT:
  323. return _T("CF_UNICODETEXT");
  324. case CF_ENHMETAFILE:
  325. return _T("CF_ENHMETAFILE");
  326. case CF_HDROP:
  327. return _T("CF_HDROP");
  328. case CF_LOCALE:
  329. return _T("CF_LOCALE");
  330. case CF_OWNERDISPLAY:
  331. return _T("CF_OWNERDISPLAY");
  332. case CF_DSPTEXT:
  333. return _T("CF_DSPTEXT");
  334. case CF_DSPBITMAP:
  335. return _T("CF_DSPBITMAP");
  336. case CF_DSPMETAFILEPICT:
  337. return _T("CF_DSPMETAFILEPICT");
  338. case CF_DSPENHMETAFILE:
  339. return _T("CF_DSPENHMETAFILE");
  340. default:
  341. //Not a default type get the name from the clipboard
  342. if (cbType != 0)
  343. {
  344. TCHAR szFormat[256];
  345. GetClipboardFormatName(cbType, szFormat, 256);
  346. return szFormat;
  347. }
  348. break;
  349. }
  350. return "ERROR";
  351. }
  352. CString GetFilePath(CString csFileName)
  353. {
  354. long lSlash = csFileName.ReverseFind('\\');
  355. if(lSlash > -1)
  356. {
  357. csFileName = csFileName.Left(lSlash + 1);
  358. }
  359. return csFileName;
  360. }
  361. CString GetFileName(CString csFileName)
  362. {
  363. long lSlash = csFileName.ReverseFind('\\');
  364. if(lSlash > -1)
  365. {
  366. csFileName = csFileName.Right(csFileName.GetLength() - lSlash - 1);
  367. }
  368. return csFileName;
  369. }
  370. /*------------------------------------------------------------------*\
  371. CHotKey - a single system-wide hotkey
  372. \*------------------------------------------------------------------*/
  373. CHotKey::CHotKey( CString name, DWORD defKey, bool bUnregOnShowDitto )
  374. : m_Name(name), m_bIsRegistered(false), m_bUnRegisterOnShowDitto(bUnregOnShowDitto)
  375. {
  376. m_Atom = ::GlobalAddAtom( m_Name );
  377. ASSERT( m_Atom );
  378. m_Key = (DWORD) g_Opt.GetProfileLong( m_Name, (long) defKey );
  379. g_HotKeys.Add( this );
  380. }
  381. CHotKey::~CHotKey()
  382. {
  383. Unregister();
  384. }
  385. void CHotKey::SetKey( DWORD key, bool bSave )
  386. {
  387. if( m_Key == key )
  388. return;
  389. if( m_bIsRegistered )
  390. Unregister();
  391. m_Key = key;
  392. if( bSave )
  393. SaveKey();
  394. }
  395. void CHotKey::LoadKey()
  396. {
  397. SetKey( (DWORD) g_Opt.GetProfileLong( m_Name, 0 ) );
  398. }
  399. bool CHotKey::SaveKey()
  400. {
  401. return g_Opt.SetProfileLong( m_Name, (long) m_Key ) != FALSE;
  402. }
  403. // CString GetKeyAsText();
  404. // void SetKeyFromText( CString text );
  405. BOOL CHotKey::ValidateHotKey(DWORD dwHotKey)
  406. {
  407. ATOM id = ::GlobalAddAtom(_T("HK_VALIDATE"));
  408. BOOL bResult = ::RegisterHotKey( g_HotKeys.m_hWnd,
  409. id,
  410. GetModifier(dwHotKey),
  411. LOBYTE(dwHotKey) );
  412. if(bResult)
  413. ::UnregisterHotKey(g_HotKeys.m_hWnd, id);
  414. ::GlobalDeleteAtom(id);
  415. return bResult;
  416. }
  417. void CHotKey::CopyFromCtrl(CHotKeyCtrl& ctrl, HWND hParent, int nWindowsCBID)
  418. {
  419. long lHotKey = ctrl.GetHotKey();
  420. short sKeyKode = LOBYTE(lHotKey);
  421. short sModifers = HIBYTE(lHotKey);
  422. if(lHotKey && ::IsDlgButtonChecked(hParent, nWindowsCBID))
  423. {
  424. sModifers |= HOTKEYF_EXT;
  425. }
  426. SetKey(MAKEWORD(sKeyKode, sModifers));
  427. }
  428. void CHotKey::CopyToCtrl(CHotKeyCtrl& ctrl, HWND hParent, int nWindowsCBID)
  429. {
  430. long lModifiers = HIBYTE(m_Key);
  431. ctrl.SetHotKey(LOBYTE(m_Key), (WORD)lModifiers);
  432. if(lModifiers & HOTKEYF_EXT)
  433. {
  434. ::CheckDlgButton(hParent, nWindowsCBID, BST_CHECKED);
  435. }
  436. }
  437. UINT CHotKey::GetModifier(DWORD dwHotKey)
  438. {
  439. UINT uMod = 0;
  440. if( HIBYTE(dwHotKey) & HOTKEYF_SHIFT ) uMod |= MOD_SHIFT;
  441. if( HIBYTE(dwHotKey) & HOTKEYF_CONTROL ) uMod |= MOD_CONTROL;
  442. if( HIBYTE(dwHotKey) & HOTKEYF_ALT ) uMod |= MOD_ALT;
  443. if( HIBYTE(dwHotKey) & HOTKEYF_EXT ) uMod |= MOD_WIN;
  444. return uMod;
  445. }
  446. bool CHotKey::Register()
  447. {
  448. if(m_Key)
  449. {
  450. if(m_bIsRegistered == false)
  451. {
  452. ASSERT(g_HotKeys.m_hWnd);
  453. m_bIsRegistered = ::RegisterHotKey(g_HotKeys.m_hWnd,
  454. m_Atom,
  455. GetModifier(),
  456. LOBYTE(m_Key) ) == TRUE;
  457. }
  458. }
  459. else
  460. m_bIsRegistered = true;
  461. return m_bIsRegistered;
  462. }
  463. bool CHotKey::Unregister(bool bOnShowingDitto)
  464. {
  465. if(!m_bIsRegistered)
  466. return true;
  467. if(bOnShowingDitto)
  468. {
  469. if(m_bUnRegisterOnShowDitto == false)
  470. return true;
  471. }
  472. if(m_Key)
  473. {
  474. ASSERT(g_HotKeys.m_hWnd);
  475. if(::UnregisterHotKey( g_HotKeys.m_hWnd, m_Atom))
  476. {
  477. m_bIsRegistered = false;
  478. return true;
  479. }
  480. else
  481. {
  482. Log(_T("Unregister FAILED!"));
  483. ASSERT(0);
  484. }
  485. }
  486. else
  487. {
  488. m_bIsRegistered = false;
  489. return true;
  490. }
  491. return false;
  492. }
  493. /*------------------------------------------------------------------*\
  494. CHotKeys - Manages system-wide hotkeys
  495. \*------------------------------------------------------------------*/
  496. CHotKeys g_HotKeys;
  497. CHotKeys::CHotKeys() : m_hWnd(NULL) {}
  498. CHotKeys::~CHotKeys()
  499. {
  500. CHotKey* pHotKey;
  501. int count = GetSize();
  502. for(int i=0; i < count; i++)
  503. {
  504. pHotKey = ElementAt(i);
  505. if(pHotKey)
  506. delete pHotKey;
  507. }
  508. }
  509. int CHotKeys::Find( CHotKey* pHotKey )
  510. {
  511. int count = GetSize();
  512. for(int i=0; i < count; i++)
  513. {
  514. if( pHotKey == ElementAt(i) )
  515. return i;
  516. }
  517. return -1;
  518. }
  519. bool CHotKeys::Remove( CHotKey* pHotKey )
  520. {
  521. int i = Find(pHotKey);
  522. if(i >= 0)
  523. {
  524. RemoveAt(i);
  525. return true;
  526. }
  527. return false;
  528. }
  529. void CHotKeys::LoadAllKeys()
  530. {
  531. int count = GetSize();
  532. for(int i=0; i < count; i++)
  533. ElementAt(i)->LoadKey();
  534. }
  535. void CHotKeys::SaveAllKeys()
  536. {
  537. int count = GetSize();
  538. for(int i=0; i < count; i++)
  539. ElementAt(i)->SaveKey();
  540. }
  541. void CHotKeys::RegisterAll(bool bMsgOnError)
  542. {
  543. CString str;
  544. CHotKey* pHotKey;
  545. int count = GetSize();
  546. for(int i = 0; i < count; i++)
  547. {
  548. pHotKey = ElementAt(i);
  549. if(!pHotKey->Register())
  550. {
  551. str = "Error Registering ";
  552. str += pHotKey->GetName();
  553. Log(str);
  554. if(bMsgOnError)
  555. AfxMessageBox(str);
  556. }
  557. }
  558. }
  559. void CHotKeys::UnregisterAll(bool bMsgOnError, bool bOnShowDitto)
  560. {
  561. CString str;
  562. CHotKey* pHotKey;
  563. int count = GetSize();
  564. for(int i = 0; i < count; i++)
  565. {
  566. pHotKey = ElementAt(i);
  567. if(!pHotKey->Unregister(bOnShowDitto))
  568. {
  569. str = "Error Unregistering ";
  570. str += pHotKey->GetName();
  571. Log(str);
  572. if(bMsgOnError)
  573. AfxMessageBox(str);
  574. }
  575. }
  576. }
  577. void CHotKeys::GetKeys(ARRAY& keys)
  578. {
  579. int count = GetSize();
  580. keys.SetSize(count);
  581. for(int i=0; i < count; i++)
  582. keys[i] = ElementAt(i)->GetKey();
  583. }
  584. // caution! this alters hotkeys based upon corresponding indexes
  585. void CHotKeys::SetKeys(ARRAY& keys, bool bSave)
  586. {
  587. int count = GetSize();
  588. ASSERT(count == keys.GetSize());
  589. for(int i=0; i < count; i++)
  590. ElementAt(i)->SetKey(keys[i], bSave);
  591. }
  592. bool CHotKeys::FindFirstConflict(ARRAY& keys, int* pX, int* pY)
  593. {
  594. bool bConflict = false;
  595. int i, j;
  596. int count = keys.GetSize();
  597. DWORD key;
  598. for(i = 0; i < count && !bConflict; i++)
  599. {
  600. key = keys.ElementAt(i);
  601. // only check valid keys
  602. if(key == 0)
  603. continue;
  604. // scan the array for a duplicate
  605. for(j = i+1; j < count; j++ )
  606. {
  607. if(keys.ElementAt(j) == key)
  608. {
  609. bConflict = true;
  610. break;
  611. }
  612. }
  613. }
  614. if(bConflict)
  615. {
  616. if(pX)
  617. *pX = i-1;
  618. if(pY)
  619. *pY = j;
  620. }
  621. return bConflict;
  622. }
  623. // if true, pX and pY (if valid) are set to the indexes of the conflicting hotkeys.
  624. bool CHotKeys::FindFirstConflict(int* pX, int* pY)
  625. {
  626. ARRAY keys;
  627. GetKeys(keys);
  628. return FindFirstConflict(keys, pX, pY);
  629. }
  630. /****************************************************************************************************
  631. BOOL CALLBACK MyMonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
  632. ***************************************************************************************************/
  633. typedef struct
  634. {
  635. long lFlags; // Flags
  636. LPRECT pVirtualRect; // Ptr to rect that receives the results, or the src of the monitor search method
  637. int iMonitor; // Ndx to the mointor to look at, -1 for all, -or- result of the monitor search method
  638. int nMonitorCount; // Total number of monitors found, -1 for monitor search method
  639. } MONITOR_ENUM_PARAM;
  640. #define MONITOR_SEARCH_METOHD 0x00000001
  641. BOOL CALLBACK MyMonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
  642. {
  643. // Typecast param
  644. MONITOR_ENUM_PARAM* pParam = (MONITOR_ENUM_PARAM*)dwData;
  645. if(pParam)
  646. {
  647. // If a dest rect was passed
  648. if(pParam->pVirtualRect)
  649. {
  650. // If MONITOR_SEARCH_METOHD then we are being asked for the index of the monitor
  651. // that the rect falls inside of
  652. if(pParam->lFlags & MONITOR_SEARCH_METOHD)
  653. {
  654. if( (pParam->pVirtualRect->right < lprcMonitor->left) ||
  655. (pParam->pVirtualRect->left > lprcMonitor->right) ||
  656. (pParam->pVirtualRect->bottom < lprcMonitor->top) ||
  657. (pParam->pVirtualRect->top > lprcMonitor->bottom))
  658. {
  659. // Nothing
  660. }
  661. else
  662. {
  663. // This is the one
  664. pParam->iMonitor = pParam->nMonitorCount;
  665. // Stop the enumeration
  666. return FALSE;
  667. }
  668. }
  669. else
  670. {
  671. if(pParam->iMonitor == pParam->nMonitorCount)
  672. {
  673. *pParam->pVirtualRect = *lprcMonitor;
  674. }
  675. else
  676. if(pParam->iMonitor == -1)
  677. {
  678. pParam->pVirtualRect->left = min(pParam->pVirtualRect->left, lprcMonitor->left);
  679. pParam->pVirtualRect->top = min(pParam->pVirtualRect->top, lprcMonitor->top);
  680. pParam->pVirtualRect->right = max(pParam->pVirtualRect->right, lprcMonitor->right);
  681. pParam->pVirtualRect->bottom = max(pParam->pVirtualRect->bottom, lprcMonitor->bottom);
  682. }
  683. }
  684. }
  685. // Up the count if necessary
  686. pParam->nMonitorCount++;
  687. }
  688. return TRUE;
  689. }
  690. int GetScreenWidth(void)
  691. {
  692. OSVERSIONINFO OS_Version_Info;
  693. DWORD dwPlatform = 0;
  694. if(GetVersionEx(&OS_Version_Info) != 0)
  695. {
  696. dwPlatform = OS_Version_Info.dwPlatformId;
  697. }
  698. if(dwPlatform == VER_PLATFORM_WIN32_NT)
  699. {
  700. int width, height;
  701. width = GetSystemMetrics(SM_CXSCREEN);
  702. height = GetSystemMetrics(SM_CYSCREEN);
  703. switch(width)
  704. {
  705. default:
  706. case 640:
  707. case 800:
  708. case 1024:
  709. return(width);
  710. case 1280:
  711. if(height == 480)
  712. {
  713. return(width / 2);
  714. }
  715. return(width);
  716. case 1600:
  717. if(height == 600)
  718. {
  719. return(width / 2);
  720. }
  721. return(width);
  722. case 2048:
  723. if(height == 768)
  724. {
  725. return(width / 2);
  726. }
  727. return(width);
  728. }
  729. }
  730. else
  731. {
  732. return(GetSystemMetrics(SM_CXSCREEN));
  733. }
  734. }
  735. int GetScreenHeight(void)
  736. {
  737. OSVERSIONINFO OS_Version_Info;
  738. DWORD dwPlatform = 0;
  739. if(GetVersionEx(&OS_Version_Info) != 0)
  740. {
  741. dwPlatform = OS_Version_Info.dwPlatformId;
  742. }
  743. if(dwPlatform == VER_PLATFORM_WIN32_NT)
  744. {
  745. int width, height;
  746. width = GetSystemMetrics(SM_CXSCREEN);
  747. height = GetSystemMetrics(SM_CYSCREEN);
  748. switch(height)
  749. {
  750. default:
  751. case 480:
  752. case 600:
  753. case 768:
  754. return(height);
  755. case 960:
  756. if(width == 640)
  757. {
  758. return(height / 2);
  759. }
  760. return(height);
  761. case 1200:
  762. if(width == 800)
  763. {
  764. return(height / 2);
  765. }
  766. return(height);
  767. case 1536:
  768. if(width == 1024)
  769. {
  770. return(height / 2);
  771. }
  772. return(height);
  773. }
  774. }
  775. else
  776. {
  777. return(GetSystemMetrics(SM_CYSCREEN));
  778. }
  779. }
  780. int GetMonitorFromRect(LPRECT lpMonitorRect)
  781. {
  782. // Build up the param
  783. MONITOR_ENUM_PARAM EnumParam;
  784. ZeroMemory(&EnumParam, sizeof(EnumParam));
  785. EnumParam.lFlags = MONITOR_SEARCH_METOHD;
  786. EnumParam.pVirtualRect = lpMonitorRect;
  787. EnumParam.iMonitor = -1;
  788. // Enum Displays
  789. EnumDisplayMonitors(NULL, NULL, MyMonitorEnumProc, (long)&EnumParam);
  790. // Return the result
  791. return EnumParam.iMonitor;
  792. }
  793. void GetMonitorRect(int iMonitor, LPRECT lpDestRect)
  794. {
  795. // Build up the param
  796. MONITOR_ENUM_PARAM EnumParam;
  797. ZeroMemory(&EnumParam, sizeof(EnumParam));
  798. EnumParam.iMonitor = iMonitor;
  799. EnumParam.pVirtualRect = lpDestRect;
  800. // Zero out dest rect
  801. lpDestRect->bottom = lpDestRect->left = lpDestRect->right = lpDestRect->top = 0;
  802. // Enum Displays
  803. EnumDisplayMonitors(NULL, NULL, MyMonitorEnumProc, (long)&EnumParam);
  804. // If not successful, default to the screen dimentions
  805. if(lpDestRect->right == 0 || lpDestRect->bottom == 0)
  806. {
  807. lpDestRect->right = GetScreenWidth();
  808. lpDestRect->bottom = GetScreenHeight();
  809. }
  810. }
  811. /*------------------------------------------------------------------*\
  812. CAccel - an Accelerator (in-app hotkey)
  813. - the win32 CreateAcceleratorTable using ACCEL was insufficient
  814. because it only allowed a WORD for the cmd associated with it.
  815. \*------------------------------------------------------------------*/
  816. /*------------------------------------------------------------------*\
  817. CAccels - Manages a set of CAccel
  818. \*------------------------------------------------------------------*/
  819. int CompareAccel( const void* pLeft, const void* pRight )
  820. {
  821. WORD w;
  822. int l,r;
  823. // swap bytes: place the VirtualKey in the MSB and the modifier in the LSB
  824. // so that Accels based upon the same vkey are grouped together.
  825. // this is required by our use of m_Index
  826. // alternatively, we could store them this way in CAccel.
  827. w = (WORD) ((CAccel*)pLeft)->Key;
  828. l = (ACCEL_VKEY(w) << 8) | ACCEL_MOD(w);
  829. w = (WORD) ((CAccel*)pRight)->Key;
  830. r = (ACCEL_VKEY(w) << 8) | ACCEL_MOD(w);
  831. return l - r;
  832. }
  833. CAccels::CAccels()
  834. {}
  835. void CAccels::AddAccel( CAccel& a )
  836. {
  837. m_Map.SetAt(a.Key, a.Cmd);
  838. }
  839. bool CAccels::OnMsg( MSG* pMsg, DWORD &dID)
  840. {
  841. // bit 30 (0x40000000) is 1 if this is NOT the first msg of the key
  842. // i.e. auto-repeat may cause multiple msgs of the same key
  843. if( (pMsg->lParam & 0x40000000) ||
  844. (pMsg->message != WM_KEYDOWN &&
  845. pMsg->message != WM_SYSKEYDOWN) )
  846. {
  847. return NULL;
  848. }
  849. if( !pMsg || m_Map.GetCount() <= 0 )
  850. return NULL;
  851. BYTE vkey = LOBYTE(pMsg->wParam);
  852. BYTE mod = GetKeyStateModifiers();
  853. DWORD key = ACCEL_MAKEKEY( vkey, mod );
  854. CString cs;
  855. cs.Format(_T("Key: %d, Mod: %d, vkey: %d"), key, mod, vkey);
  856. OutputDebugString(cs);
  857. if(m_Map.Lookup(key, dID))
  858. return true;;
  859. return false;
  860. }
  861. BYTE GetKeyStateModifiers()
  862. {
  863. BYTE m=0;
  864. if( GetKeyState(VK_SHIFT) & 0x8000 )
  865. m |= HOTKEYF_SHIFT;
  866. if( GetKeyState(VK_CONTROL) & 0x8000 )
  867. m |= HOTKEYF_CONTROL;
  868. if( GetKeyState(VK_MENU) & 0x8000 )
  869. m |= HOTKEYF_ALT;
  870. if( GetKeyState(VK_LWIN) & 0x8000 )
  871. m |= HOTKEYF_EXT;
  872. if( GetKeyState(VK_RWIN) & 0x8000 )
  873. m |= HOTKEYF_EXT;
  874. return m;
  875. }
  876. /*------------------------------------------------------------------*\
  877. CTokenizer - Tokenizes a string using given delimiters
  878. \*------------------------------------------------------------------*/
  879. CTokenizer::CTokenizer(const CString& cs, const CString& csDelim):
  880. m_cs(cs),
  881. m_nCurPos(0)
  882. {
  883. SetDelimiters(csDelim);
  884. }
  885. void CTokenizer::SetDelimiters(const CString& csDelim)
  886. {
  887. for(int i = 0; i < csDelim.GetLength(); ++i)
  888. m_delim.Add(csDelim[i]);
  889. m_delim.SortAscending();
  890. }
  891. bool CTokenizer::Next(CString& cs)
  892. {
  893. cs.Empty();
  894. int len = m_cs.GetLength();
  895. while (m_nCurPos < len && m_delim.Find(m_cs[m_nCurPos]))
  896. ++ m_nCurPos;
  897. if (m_nCurPos >= len)
  898. return false;
  899. int nStartPos = m_nCurPos;
  900. while (m_nCurPos < len && !m_delim.Find(m_cs[m_nCurPos]))
  901. ++ m_nCurPos;
  902. cs = m_cs.Mid(nStartPos, m_nCurPos - nStartPos);
  903. return true;
  904. }
  905. CString CTokenizer::Tail()
  906. {
  907. int len = m_cs.GetLength();
  908. int nCurPos = m_nCurPos;
  909. while(nCurPos < len && m_delim.Find(m_cs[nCurPos]))
  910. ++nCurPos;
  911. CString csResult;
  912. if(nCurPos < len)
  913. csResult = m_cs.Mid(nCurPos);
  914. return csResult;
  915. }
  916. /*------------------------------------------------------------------*\
  917. Global ToolTip Manual Control Functions
  918. \*------------------------------------------------------------------*/
  919. void InitToolInfo( TOOLINFO& ti )
  920. {
  921. // INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE
  922. ti.cbSize = sizeof(TOOLINFO);
  923. ti.uFlags = TTF_ABSOLUTE | TTF_TRACK;
  924. ti.hwnd = NULL;
  925. ti.hinst = NULL;
  926. ti.uId = 0; // CPopup only uses uid 0
  927. ti.lpszText = NULL;
  928. // ToolTip control will cover the whole window
  929. ti.rect.left = 0;
  930. ti.rect.top = 0;
  931. ti.rect.right = 0;
  932. ti.rect.bottom = 0;
  933. }
  934. /*------------------------------------------------------------------*\
  935. CPopup - a tooltip that pops up manually (when Show is called).
  936. - technique learned from codeproject "ToolTipZen" by "Zarembo Maxim"
  937. \*------------------------------------------------------------------*/
  938. CPopup::CPopup()
  939. {
  940. Init();
  941. }
  942. // HWND_TOP
  943. CPopup::CPopup( int x, int y, HWND hWndPosRelativeTo, HWND hWndInsertAfter )
  944. {
  945. Init();
  946. m_hWndPosRelativeTo = hWndPosRelativeTo;
  947. m_hWndInsertAfter = hWndInsertAfter;
  948. SetPos( CPoint(x,y) );
  949. }
  950. CPopup::~CPopup()
  951. {
  952. Hide();
  953. if( m_bOwnTT && ::IsWindow(m_hTTWnd) )
  954. ::DestroyWindow( m_hTTWnd );
  955. }
  956. void CPopup::Init()
  957. {
  958. // initialize variables
  959. m_bOwnTT = false;
  960. m_hTTWnd = NULL;
  961. m_bIsShowing = false;
  962. m_bAllowShow = true; // used by AllowShow()
  963. m_Pos.x = m_Pos.y = 0;
  964. m_bTop = true;
  965. m_bLeft = true;
  966. m_bCenterX = false;
  967. m_bCenterY = false;
  968. m_hWndPosRelativeTo = NULL;
  969. RECT rcScreen;
  970. GetMonitorRect(-1, &rcScreen);
  971. m_ScreenMaxX = rcScreen.right;
  972. m_ScreenMaxY = rcScreen.bottom;
  973. m_hWndInsertAfter = HWND_TOP; //HWND_TOPMOST
  974. SetTTWnd();
  975. }
  976. void CPopup::SetTTWnd( HWND hTTWnd, TOOLINFO* pTI )
  977. {
  978. if( pTI )
  979. m_TI = *pTI;
  980. else
  981. InitToolInfo( m_TI );
  982. if( m_bOwnTT && ::IsWindow(m_hTTWnd) )
  983. {
  984. if( !::IsWindow(hTTWnd) )
  985. return; // we would have to recreate the one that already exists
  986. ::DestroyWindow( m_hTTWnd );
  987. }
  988. m_hTTWnd = hTTWnd;
  989. if( ::IsWindow(m_hTTWnd) )
  990. {
  991. m_bOwnTT = false;
  992. // if our uid tooltip already exists, get the data, else add it.
  993. if( ! ::SendMessage(m_hTTWnd, TTM_GETTOOLINFO, 0, (LPARAM)(LPTOOLINFO) &m_TI) )
  994. ::SendMessage(m_hTTWnd, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &m_TI);
  995. }
  996. else
  997. {
  998. m_bOwnTT = true;
  999. CreateToolTip();
  1000. }
  1001. }
  1002. void CPopup::CreateToolTip()
  1003. {
  1004. if( m_hTTWnd != NULL )
  1005. return;
  1006. // CREATE A TOOLTIP WINDOW
  1007. m_hTTWnd = CreateWindowEx(
  1008. WS_EX_TOPMOST,
  1009. TOOLTIPS_CLASS,
  1010. NULL,
  1011. TTS_NOPREFIX | TTS_ALWAYSTIP,
  1012. CW_USEDEFAULT,
  1013. CW_USEDEFAULT,
  1014. CW_USEDEFAULT,
  1015. CW_USEDEFAULT,
  1016. NULL,
  1017. NULL,
  1018. NULL,
  1019. NULL
  1020. );
  1021. m_bOwnTT = true;
  1022. // SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW
  1023. ::SendMessage(m_hTTWnd, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &m_TI);
  1024. }
  1025. void CPopup::SetTimeout( int timeout )
  1026. {
  1027. if( m_hTTWnd == NULL )
  1028. return;
  1029. ::SendMessage(m_hTTWnd, TTM_SETDELAYTIME, TTDT_AUTOMATIC, timeout);
  1030. }
  1031. void CPopup::SetPos( CPoint& pos )
  1032. {
  1033. m_Pos = pos;
  1034. }
  1035. void CPopup::SetPosInfo( bool bTop, bool bCenterY, bool bLeft, bool bCenterX )
  1036. {
  1037. m_bTop = bTop;
  1038. m_bCenterY = bCenterY;
  1039. m_bLeft = bLeft;
  1040. m_bCenterX = bCenterX;
  1041. }
  1042. void CPopup::AdjustPos( CPoint& pos )
  1043. {
  1044. CRect rel(0,0,0,0);
  1045. CRect rect(0,0,0,0);
  1046. // ::SendMessage(m_hTTWnd, TTM_ADJUSTRECT, TRUE, (LPARAM)&rect);
  1047. ::GetWindowRect(m_hTTWnd,&rect);
  1048. if( ::IsWindow(m_hWndPosRelativeTo) )
  1049. ::GetWindowRect(m_hWndPosRelativeTo, &rel);
  1050. // move the rect to the relative origin
  1051. rect.bottom = rect.Height() + rel.top;
  1052. rect.top = rel.top;
  1053. rect.right = rect.Width() + rel.left;
  1054. rect.left = rel.left;
  1055. // adjust the y position
  1056. rect.OffsetRect( 0, pos.y - (m_bCenterY? rect.Height()/2: (m_bTop? 0: rect.Height())) );
  1057. if( rect.bottom > m_ScreenMaxY )
  1058. rect.OffsetRect( 0, m_ScreenMaxY - rect.bottom );
  1059. // adjust the x position
  1060. rect.OffsetRect( pos.x - (m_bCenterX? rect.Width()/2: (m_bLeft? 0: rect.Width())), 0 );
  1061. if( rect.right > m_ScreenMaxX )
  1062. rect.OffsetRect( m_ScreenMaxX - rect.right, 0 );
  1063. pos.x = rect.left;
  1064. pos.y = rect.top;
  1065. }
  1066. void CPopup::SendToolTipText( CString text )
  1067. {
  1068. m_csToolTipText = text;
  1069. //Replace the tabs with spaces, the tooltip didn't like the \t s
  1070. text.Replace(_T("\t"), _T(" "));
  1071. m_TI.lpszText = (LPTSTR) (LPCTSTR) text;
  1072. // this allows \n and \r to be interpreted correctly
  1073. ::SendMessage(m_hTTWnd, TTM_SETMAXTIPWIDTH, 0, 500);
  1074. // set the text
  1075. ::SendMessage(m_hTTWnd, TTM_SETTOOLINFO, 0, (LPARAM) (LPTOOLINFO) &m_TI);
  1076. }
  1077. void CPopup::Show( CString text, CPoint pos, bool bAdjustPos )
  1078. {
  1079. if( m_hTTWnd == NULL )
  1080. return;
  1081. m_csToolTipText = text;
  1082. if( !m_bIsShowing )
  1083. ::SendMessage(m_hTTWnd, TTM_TRACKPOSITION, 0, (LPARAM)(DWORD) MAKELONG(-10000,-10000));
  1084. SendToolTipText( text );
  1085. ::SendMessage(m_hTTWnd, TTM_TRACKACTIVATE, true, (LPARAM)(LPTOOLINFO) &m_TI);
  1086. if( bAdjustPos )
  1087. AdjustPos(pos);
  1088. // set the position
  1089. ::SendMessage(m_hTTWnd, TTM_TRACKPOSITION, 0, (LPARAM)(DWORD) MAKELONG(pos.x,pos.y));
  1090. // make sure the tooltip will be on top.
  1091. ::SetWindowPos( m_hTTWnd, m_hWndInsertAfter, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE );
  1092. m_bIsShowing = true;
  1093. }
  1094. void CPopup::Show( CString text )
  1095. {
  1096. m_csToolTipText = text;
  1097. Show( text, m_Pos );
  1098. }
  1099. void CPopup::AllowShow( CString text )
  1100. {
  1101. m_csToolTipText = text;
  1102. if( m_bAllowShow )
  1103. Show( text, m_Pos );
  1104. }
  1105. void CPopup::Hide()
  1106. {
  1107. if( m_hTTWnd == NULL )
  1108. return;
  1109. // deactivate if it is currently activated
  1110. ::SendMessage(m_hTTWnd, TTM_TRACKACTIVATE, FALSE, (LPARAM)(LPTOOLINFO) &m_TI);
  1111. m_bIsShowing = false;
  1112. }
  1113. /*------------------------------------------------------------------*\
  1114. ID based Globals
  1115. \*------------------------------------------------------------------*/
  1116. long NewGroupID(long lParentID, CString text)
  1117. {
  1118. long lID=0;
  1119. CTime time;
  1120. time = CTime::GetCurrentTime();
  1121. try
  1122. {
  1123. //sqlite doesn't like single quotes ' replace them with double ''
  1124. if(text.IsEmpty())
  1125. text = time.Format("NewGroup %y/%m/%d %H:%M:%S");
  1126. text.Replace(_T("'"), _T("''"));
  1127. CString cs;
  1128. cs.Format(_T("insert into Main values(NULL, %d, '%s', 0, %d, 0, 1, %d, '');"),
  1129. (long)time.GetTime(),
  1130. text,
  1131. (long)time.GetTime(),
  1132. lParentID);
  1133. theApp.m_db.execDML(cs);
  1134. lID = (long)theApp.m_db.lastRowId();
  1135. }
  1136. CATCH_SQLITE_EXCEPTION_AND_RETURN(0)
  1137. return lID;
  1138. }
  1139. // deletes the given item
  1140. BOOL DeleteID(long lID)
  1141. {
  1142. BOOL bRet = FALSE;
  1143. try
  1144. {
  1145. bool bCont = false;
  1146. bool bGroup = false;
  1147. {
  1148. CppSQLite3Query q = theApp.m_db.execQueryEx(_T("SELECT bIsGroup FROM Main WHERE lId = %d"), lID);
  1149. bCont = !q.eof();
  1150. if(bCont)
  1151. {
  1152. bGroup = q.getIntField(_T("bIsGroup")) > 0;
  1153. }
  1154. }
  1155. if(bCont)
  1156. {
  1157. if(bGroup)
  1158. {
  1159. theApp.m_db.execDMLEx(_T("UPDATE Main SET lParentID = -1 WHERE lParentID = %d;"), lID);
  1160. }
  1161. //now is deleted from a trigger
  1162. //theApp.m_db.execDMLEx(_T("DELETE FROM Data WHERE lParentID = %d;"), lID);
  1163. theApp.m_db.execDMLEx(_T("DELETE FROM Main WHERE lID = %d;"), lID);
  1164. bRet = TRUE;
  1165. }
  1166. theApp.OnDeleteID(lID);
  1167. }
  1168. CATCH_SQLITE_EXCEPTION_AND_RETURN(FALSE)
  1169. return bRet;
  1170. }
  1171. BOOL DeleteAllIDs()
  1172. {
  1173. try
  1174. {
  1175. theApp.m_db.execDML(_T("DELETE FROM Data;"));
  1176. theApp.m_db.execDML(_T("DELETE FROM Main;"));
  1177. }
  1178. CATCH_SQLITE_EXCEPTION
  1179. return TRUE;
  1180. }
  1181. BOOL DeleteFormats(long lParentID, ARRAY& formatIDs)
  1182. {
  1183. if(formatIDs.GetSize() <= 0)
  1184. return TRUE;
  1185. try
  1186. {
  1187. //Delete the requested data formats
  1188. int nCount = formatIDs.GetSize();
  1189. for(int i = 0; i < nCount; i++)
  1190. {
  1191. theApp.m_db.execDMLEx(_T("DELETE FROM Data WHERE lID = %d;"), formatIDs[i]);
  1192. }
  1193. CClip clip;
  1194. if(clip.LoadFormats(lParentID))
  1195. {
  1196. DWORD CRC = clip.GenerateCRC();
  1197. //Update the main table with new size
  1198. theApp.m_db.execDMLEx(_T("UPDATE Main SET CRC = %d WHERE lID = %d"), CRC, lParentID);
  1199. }
  1200. }
  1201. CATCH_SQLITE_EXCEPTION
  1202. return TRUE;
  1203. }
  1204. BOOL EnsureWindowVisible(CRect *pcrRect)
  1205. {
  1206. int nMonitor = GetMonitorFromRect(pcrRect);
  1207. if(nMonitor < 0)
  1208. {
  1209. GetMonitorRect(0, pcrRect);
  1210. pcrRect->right = pcrRect->left + 300;
  1211. pcrRect->bottom = pcrRect->top + 300;
  1212. return TRUE;
  1213. }
  1214. CRect crMonitor;
  1215. GetMonitorRect(nMonitor, crMonitor);
  1216. //Validate the left
  1217. long lDiff = pcrRect->left - crMonitor.left;
  1218. if(lDiff < 0)
  1219. {
  1220. pcrRect->left += abs(lDiff);
  1221. pcrRect->right += abs(lDiff);
  1222. }
  1223. //Right side
  1224. lDiff = pcrRect->right - crMonitor.right;
  1225. if(lDiff > 0)
  1226. {
  1227. pcrRect->left -= abs(lDiff);
  1228. pcrRect->right -= abs(lDiff);
  1229. }
  1230. //Top
  1231. lDiff = pcrRect->top - crMonitor.top;
  1232. if(lDiff < 0)
  1233. {
  1234. pcrRect->top += abs(lDiff);
  1235. pcrRect->bottom += abs(lDiff);
  1236. }
  1237. //Bottom
  1238. lDiff = pcrRect->bottom - crMonitor.bottom;
  1239. if(lDiff > 0)
  1240. {
  1241. pcrRect->top -= abs(lDiff);
  1242. pcrRect->bottom -= abs(lDiff);
  1243. }
  1244. return TRUE;
  1245. }
  1246. __int64 GetLastWriteTime(const CString &csFile)
  1247. {
  1248. __int64 nLastWrite = 0;
  1249. CFileFind finder;
  1250. BOOL bResult = finder.FindFile(csFile);
  1251. if (bResult)
  1252. {
  1253. finder.FindNextFile();
  1254. FILETIME ft;
  1255. finder.GetLastWriteTime(&ft);
  1256. memcpy(&nLastWrite, &ft, sizeof(ft));
  1257. }
  1258. return nLastWrite;
  1259. }
  1260. CString GetProcessName(HWND hWnd)
  1261. {
  1262. DWORD Id;
  1263. GetWindowThreadProcessId(hWnd, &Id);
  1264. PROCESSENTRY32 processEntry = { 0 };
  1265. HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  1266. processEntry.dwSize = sizeof(PROCESSENTRY32);
  1267. if (Process32First(hSnapShot, &processEntry))
  1268. {
  1269. do
  1270. {
  1271. if (processEntry.th32ProcessID == Id)
  1272. {
  1273. return processEntry.szExeFile;
  1274. }
  1275. } while(Process32Next(hSnapShot, &processEntry));
  1276. }
  1277. CloseHandle(hSnapShot);
  1278. return "";
  1279. }
  1280. BOOL IsVista()
  1281. {
  1282. OSVERSIONINFO osver;
  1283. osver.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
  1284. if (::GetVersionEx( &osver ) &&
  1285. osver.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  1286. (osver.dwMajorVersion >= 6 ) )
  1287. {
  1288. return TRUE;
  1289. }
  1290. return FALSE;
  1291. }
  1292. bool IsRunningLimited()
  1293. {
  1294. LPCTSTR pszSubKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
  1295. LPCTSTR pszValue = _T("EnableLUA");
  1296. DWORD dwType = 0;
  1297. DWORD dwValue = 0;
  1298. DWORD dwValueSize = sizeof(DWORD);
  1299. if(ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, pszSubKey, pszValue, &dwType, &dwValue, &dwValueSize))
  1300. {
  1301. //failed to read the reg key, either it's not there or we don't have access to the registry
  1302. //If we are vista then assume we don't have access and we are running as a limited app
  1303. //otherwise we are xp and the reg key probably doesn't exist and we are not a limited running app
  1304. if(IsVista())
  1305. {
  1306. OutputDebugString(_T("Ditto - Failed to read registry entry finding UAC, Running as limited application"));
  1307. return true;
  1308. }
  1309. }
  1310. if(dwValue == 1)
  1311. {
  1312. OutputDebugString(_T("Ditto - UAC ENABLED, Running as limited application"));
  1313. return true;
  1314. }
  1315. OutputDebugString(_T("Ditto - Running as standard application"));
  1316. return false;
  1317. }