1
0

Misc.cpp 33 KB

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