Misc.cpp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991
  1. #include "stdafx.h"
  2. #include "CP_Main.h"
  3. #include "Misc.h"
  4. #include "OptionsSheet.h"
  5. #ifdef AFTER_98
  6. #include "AlphaBlend.h"
  7. #endif
  8. // Debug Functions
  9. int GetCBitmapWidth(const CBitmap & cbm)
  10. {
  11. BITMAP bm;
  12. cbm.GetObject(sizeof(BITMAP),&bm);
  13. return bm.bmWidth;
  14. }
  15. int GetCBitmapHeight(const CBitmap & cbm)
  16. {
  17. BITMAP bm;
  18. cbm.GetObject(sizeof(BITMAP),&bm);
  19. return bm.bmHeight;
  20. }
  21. BOOL GetCBitmap(void *pClip2, CDC *pDC, CBitmap *pBitMap, int nMaxHeight)
  22. {
  23. LPBITMAPINFO lpBI ;
  24. void* pDIBBits;
  25. BOOL bRet = FALSE;
  26. CClipFormat *pClip = (CClipFormat *)pClip2;
  27. switch(pClip->m_cfType)
  28. {
  29. case CF_DIB:
  30. {
  31. lpBI = (LPBITMAPINFO)GlobalLock(pClip->m_hgData);
  32. if(lpBI)
  33. {
  34. pDIBBits = (void*)(lpBI->bmiColors + sizeof(RGBQUAD));
  35. int nHeight = min(nMaxHeight, lpBI->bmiHeader.biHeight);
  36. int nWidth = (nHeight * lpBI->bmiHeader.biWidth) / lpBI->bmiHeader.biHeight;
  37. if(pBitMap)
  38. {
  39. pBitMap->CreateCompatibleBitmap(pDC, nWidth, nHeight);
  40. CDC MemDc;
  41. MemDc.CreateCompatibleDC(pDC);
  42. CBitmap* oldBitmap = MemDc.SelectObject(pBitMap);
  43. ::StretchDIBits(MemDc.m_hDC,
  44. 0, 0,
  45. nWidth, nHeight,
  46. 0, 0, lpBI->bmiHeader.biWidth,
  47. lpBI->bmiHeader.biHeight,
  48. pDIBBits, lpBI, DIB_PAL_COLORS, SRCCOPY);
  49. MemDc.SelectObject(oldBitmap);
  50. bRet = TRUE;
  51. }
  52. }
  53. }
  54. }
  55. return bRet;
  56. }
  57. CString GetIPAddress()
  58. {
  59. WORD wVersionRequested;
  60. WSADATA wsaData;
  61. char name[255];
  62. CString IP;
  63. PHOSTENT hostinfo;
  64. wVersionRequested = MAKEWORD(2,0);
  65. if (WSAStartup(wVersionRequested, &wsaData)==0)
  66. {
  67. if(gethostname(name, sizeof(name))==0)
  68. {
  69. if((hostinfo=gethostbyname(name)) != NULL)
  70. {
  71. IP = inet_ntoa(*(struct in_addr*)* hostinfo->h_addr_list);
  72. }
  73. }
  74. WSACleanup();
  75. }
  76. IP.MakeUpper();
  77. return IP;
  78. }
  79. CString GetComputerName()
  80. {
  81. char ComputerName[MAX_COMPUTERNAME_LENGTH+1]="";
  82. DWORD Size=MAX_COMPUTERNAME_LENGTH+1;
  83. GetComputerName(ComputerName, &Size);
  84. CString cs(ComputerName);
  85. cs.MakeUpper();
  86. return cs;
  87. }
  88. void AppendToFile( const char* fn, const char* msg )
  89. {
  90. FILE *file = fopen(fn, "a");
  91. ASSERT( file );
  92. fprintf(file, msg);
  93. fclose(file);
  94. }
  95. void Log( const char* msg )
  96. {
  97. ASSERT( AfxIsValidString(msg) );
  98. CTime time = CTime::GetCurrentTime();
  99. CString csText = time.Format("[%Y/%m/%d %I:%M:%S %p] ");
  100. //CString csTemp;
  101. // csTemp.Format( "%04x ", AfxGetInstanceHandle() );
  102. csText += msg;
  103. csText += "\n";
  104. TRACE(csText);
  105. AppendToFile( "Ditto.log", csText ); //(LPCTSTR)
  106. }
  107. void LogSendRecieveInfo(CString cs)
  108. {
  109. if(g_Opt.m_bLogSendReceiveErrors)
  110. Log(cs);
  111. }
  112. CString GetErrorString( int err )
  113. {
  114. CString str;
  115. LPVOID lpMsgBuf;
  116. ::FormatMessage(
  117. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  118. NULL,
  119. err,
  120. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  121. (LPTSTR) &lpMsgBuf,
  122. 0,
  123. NULL
  124. );
  125. str = (LPCTSTR) lpMsgBuf;
  126. // Display the string.
  127. // ::MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
  128. ::LocalFree( lpMsgBuf );
  129. return str;
  130. }
  131. void SetThreadName(DWORD dwThreadID, LPCTSTR szThreadName)
  132. {
  133. THREADNAME_INFO info;
  134. info.dwType = 0x1000;
  135. info.szName = szThreadName;
  136. info.dwThreadID = dwThreadID;
  137. info.dwFlags = 0;
  138. __try
  139. {
  140. RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(DWORD), (DWORD *)&info);
  141. }
  142. __except (EXCEPTION_CONTINUE_EXECUTION)
  143. {
  144. }
  145. }
  146. // Utility Functions
  147. CString StrF(const char * pszFormat, ...)
  148. {
  149. ASSERT( AfxIsValidString( pszFormat ) );
  150. CString str;
  151. va_list argList;
  152. va_start( argList, pszFormat );
  153. str.FormatV( pszFormat, argList );
  154. va_end( argList );
  155. return str;
  156. }
  157. BYTE GetEscapeChar( BYTE ch )
  158. {
  159. switch(ch)
  160. {
  161. case '\'': return '\''; // Single quotation mark (') = 39 or 0x27
  162. case '\"': return '\"'; // Double quotation mark (") = 34 or 0x22
  163. case '?': return '\?'; // Question mark (?) = 63 or 0x3f
  164. case '\\': return '\\'; // Backslash (\) = 92 or 0x5c
  165. case 'a': return '\a'; // Alert (BEL) = 7
  166. case 'b': return '\b'; // Backspace (BS) = 8
  167. case 'f': return '\f'; // Formfeed (FF) = 12 or 0x0c
  168. case 'n': return '\n'; // Newline (NL or LF) = 10 or 0x0a
  169. case 'r': return '\r'; // Carriage Return (CR) = 13 or 0x0d
  170. case 't': return '\t'; // Horizontal tab (HT) = 9
  171. case 'v': return '\v'; // Vertical tab (VT) = 11 or 0x0b
  172. case '0': return '\0'; // Null character (NUL) = 0
  173. }
  174. return 0; // invalid
  175. }
  176. CString RemoveEscapes( const char* str )
  177. {
  178. ASSERT( str );
  179. CString ret;
  180. char* pSrc = (char*) str;
  181. char* pDest = ret.GetBuffer( strlen(pSrc) );
  182. char* pStart = pDest;
  183. while( *pSrc != '\0' )
  184. {
  185. if( *pSrc == '\\' )
  186. {
  187. pSrc++;
  188. *pDest = GetEscapeChar( *pSrc );
  189. }
  190. else
  191. *pDest = *pSrc;
  192. pSrc++;
  193. pDest++;
  194. }
  195. ret.ReleaseBuffer( pDest - pStart );
  196. return ret;
  197. }
  198. CString GetWndText( HWND hWnd )
  199. {
  200. CString text;
  201. if( !IsWindow(hWnd) )
  202. return "! NOT A VALID WINDOW !";
  203. CWnd* pWnd = CWnd::FromHandle(hWnd);
  204. pWnd->GetWindowText(text);
  205. return text;
  206. }
  207. bool IsAppWnd( HWND hWnd )
  208. {
  209. DWORD dwMyPID = ::GetCurrentProcessId();
  210. DWORD dwTestPID;
  211. ::GetWindowThreadProcessId( hWnd, &dwTestPID );
  212. return dwMyPID == dwTestPID;
  213. }
  214. HWND GetFocusWnd(CPoint *pPointCaret)
  215. {
  216. HWND hWndFocus = NULL;
  217. if (pPointCaret)
  218. *pPointCaret = CPoint(-1, -1);
  219. HWND hWndForground = GetForegroundWindow(); // Get the desktop's foreground window
  220. if (hWndForground != NULL)
  221. {
  222. DWORD ProcID;
  223. DWORD ThreadID = GetWindowThreadProcessId(hWndForground, &ProcID);
  224. // Attach other thread's message queue to our own to ensure GetFocus() is working properly
  225. BOOL ARes = AttachThreadInput(ThreadID, GetCurrentThreadId(), TRUE);
  226. if (ARes)
  227. {
  228. // Get the other thread's focussed window
  229. CWnd *pWnd = CWnd::FromHandle(hWndForground);
  230. if (pWnd)
  231. {
  232. CWnd *pWndFocus = pWnd->GetFocus();
  233. if (pWndFocus)
  234. {
  235. hWndFocus = pWndFocus->m_hWnd;
  236. if (pPointCaret)
  237. {
  238. *pPointCaret = pWndFocus->GetCaretPos();
  239. pWndFocus->ClientToScreen(pPointCaret);
  240. }
  241. }
  242. }
  243. // Detach other thread's message queue from our own again
  244. ARes = AttachThreadInput(ThreadID, GetCurrentThreadId(), FALSE);
  245. }
  246. }
  247. return hWndFocus;
  248. }
  249. /*----------------------------------------------------------------------------*\
  250. Global Memory Helper Functions
  251. \*----------------------------------------------------------------------------*/
  252. // make sure the given HGLOBAL is valid.
  253. BOOL IsValid( HGLOBAL hGlobal )
  254. {
  255. void* pvData = ::GlobalLock( hGlobal );
  256. ::GlobalUnlock( hGlobal );
  257. return ( pvData != NULL );
  258. }
  259. // asserts if hDest isn't big enough
  260. void CopyToGlobalHP( HGLOBAL hDest, LPVOID pBuf, ULONG ulBufLen )
  261. {
  262. ASSERT( hDest && pBuf && ulBufLen );
  263. LPVOID pvData = GlobalLock(hDest);
  264. ASSERT( pvData );
  265. ULONG size = GlobalSize(hDest);
  266. ASSERT( size >= ulBufLen ); // assert if hDest isn't big enough
  267. memcpy(pvData, pBuf, ulBufLen);
  268. GlobalUnlock(hDest);
  269. }
  270. void CopyToGlobalHH( HGLOBAL hDest, HGLOBAL hSource, ULONG ulBufLen )
  271. {
  272. ASSERT( hDest && hSource && ulBufLen );
  273. LPVOID pvData = GlobalLock(hSource);
  274. ASSERT( pvData );
  275. ULONG size = GlobalSize(hSource);
  276. ASSERT( size >= ulBufLen ); // assert if hSource isn't big enough
  277. CopyToGlobalHP(hDest, pvData, ulBufLen);
  278. GlobalUnlock(hSource);
  279. }
  280. HGLOBAL NewGlobalP( LPVOID pBuf, UINT nLen )
  281. {
  282. ASSERT( pBuf && nLen );
  283. HGLOBAL hDest = GlobalAlloc( GMEM_MOVEABLE | GMEM_SHARE, nLen );
  284. ASSERT( hDest );
  285. CopyToGlobalHP( hDest, pBuf, nLen );
  286. return hDest;
  287. }
  288. HGLOBAL NewGlobal(UINT nLen)
  289. {
  290. ASSERT(nLen);
  291. HGLOBAL hDest = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, nLen);
  292. return hDest;
  293. }
  294. HGLOBAL NewGlobalH( HGLOBAL hSource, UINT nLen )
  295. {
  296. ASSERT( hSource && nLen );
  297. LPVOID pvData = GlobalLock( hSource );
  298. HGLOBAL hDest = NewGlobalP( pvData, nLen );
  299. GlobalUnlock( hSource );
  300. return hDest;
  301. }
  302. int CompareGlobalHP( HGLOBAL hLeft, LPVOID pBuf, ULONG ulBufLen )
  303. {
  304. ASSERT( hLeft && pBuf && ulBufLen );
  305. LPVOID pvData = GlobalLock( hLeft );
  306. ASSERT( pvData );
  307. ASSERT( ulBufLen <= GlobalSize(hLeft) );
  308. int result = memcmp(pvData, pBuf, ulBufLen);
  309. GlobalUnlock( hLeft );
  310. return result;
  311. }
  312. int CompareGlobalHH( HGLOBAL hLeft, HGLOBAL hRight, ULONG ulBufLen )
  313. {
  314. ASSERT( hLeft && hRight && ulBufLen );
  315. ASSERT( ulBufLen <= GlobalSize(hRight) );
  316. LPVOID pvData = GlobalLock(hRight);
  317. ASSERT( pvData );
  318. int result = CompareGlobalHP( hLeft, pvData, ulBufLen );
  319. GlobalUnlock( hLeft );
  320. return result;
  321. }
  322. long DoOptions(CWnd *pParent)
  323. {
  324. //Don't let it open up more than once
  325. if(theApp.m_bShowingOptions)
  326. return FALSE;
  327. theApp.m_bShowingOptions = true;
  328. COptionsSheet Sheet("Copy Pro Options", pParent);
  329. int nRet = Sheet.DoModal();
  330. theApp.m_bShowingOptions = false;
  331. return nRet;
  332. }
  333. //Do not change these these are stored in the database
  334. CLIPFORMAT GetFormatID(LPCSTR cbName)
  335. {
  336. if(strcmp(cbName, "CF_TEXT") == 0)
  337. return CF_TEXT;
  338. else if(strcmp(cbName, "CF_METAFILEPICT") == 0)
  339. return CF_METAFILEPICT;
  340. else if(strcmp(cbName, "CF_SYLK") == 0)
  341. return CF_SYLK;
  342. else if(strcmp(cbName, "CF_DIF") == 0)
  343. return CF_DIF;
  344. else if(strcmp(cbName, "CF_TIFF") == 0)
  345. return CF_TIFF;
  346. else if(strcmp(cbName, "CF_OEMTEXT") == 0)
  347. return CF_OEMTEXT;
  348. else if(strcmp(cbName, "CF_DIB") == 0)
  349. return CF_DIB;
  350. else if(strcmp(cbName, "CF_PALETTE") == 0)
  351. return CF_PALETTE;
  352. else if(strcmp(cbName, "CF_PENDATA") == 0)
  353. return CF_PENDATA;
  354. else if(strcmp(cbName, "CF_RIFF") == 0)
  355. return CF_RIFF;
  356. else if(strcmp(cbName, "CF_WAVE") == 0)
  357. return CF_WAVE;
  358. else if(strcmp(cbName, "CF_UNICODETEXT") == 0)
  359. return CF_UNICODETEXT;
  360. else if(strcmp(cbName, "CF_ENHMETAFILE") == 0)
  361. return CF_ENHMETAFILE;
  362. else if(strcmp(cbName, "CF_HDROP") == 0)
  363. return CF_HDROP;
  364. else if(strcmp(cbName, "CF_LOCALE") == 0)
  365. return CF_LOCALE;
  366. else if(strcmp(cbName, "CF_OWNERDISPLAY") == 0)
  367. return CF_OWNERDISPLAY;
  368. else if(strcmp(cbName, "CF_DSPTEXT") == 0)
  369. return CF_DSPTEXT;
  370. else if(strcmp(cbName, "CF_DSPBITMAP") == 0)
  371. return CF_DSPBITMAP;
  372. else if(strcmp(cbName, "CF_DSPMETAFILEPICT") == 0)
  373. return CF_DSPMETAFILEPICT;
  374. else if(strcmp(cbName, "CF_DSPENHMETAFILE") == 0)
  375. return CF_DSPENHMETAFILE;
  376. return ::RegisterClipboardFormat(cbName);
  377. }
  378. //Do not change these these are stored in the database
  379. CString GetFormatName(CLIPFORMAT cbType)
  380. {
  381. switch(cbType)
  382. {
  383. case CF_TEXT:
  384. return "CF_TEXT";
  385. case CF_BITMAP:
  386. return "CF_BITMAP";
  387. case CF_METAFILEPICT:
  388. return "CF_METAFILEPICT";
  389. case CF_SYLK:
  390. return "CF_SYLK";
  391. case CF_DIF:
  392. return "CF_DIF";
  393. case CF_TIFF:
  394. return "CF_TIFF";
  395. case CF_OEMTEXT:
  396. return "CF_OEMTEXT";
  397. case CF_DIB:
  398. return "CF_DIB";
  399. case CF_PALETTE:
  400. return "CF_PALETTE";
  401. case CF_PENDATA:
  402. return "CF_PENDATA";
  403. case CF_RIFF:
  404. return "CF_RIFF";
  405. case CF_WAVE:
  406. return "CF_WAVE";
  407. case CF_UNICODETEXT:
  408. return "CF_UNICODETEXT";
  409. case CF_ENHMETAFILE:
  410. return "CF_ENHMETAFILE";
  411. case CF_HDROP:
  412. return "CF_HDROP";
  413. case CF_LOCALE:
  414. return "CF_LOCALE";
  415. case CF_OWNERDISPLAY:
  416. return "CF_OWNERDISPLAY";
  417. case CF_DSPTEXT:
  418. return "CF_DSPTEXT";
  419. case CF_DSPBITMAP:
  420. return "CF_DSPBITMAP";
  421. case CF_DSPMETAFILEPICT:
  422. return "CF_DSPMETAFILEPICT";
  423. case CF_DSPENHMETAFILE:
  424. return "CF_DSPENHMETAFILE";
  425. default:
  426. //Not a default type get the name from the clipboard
  427. if (cbType != 0)
  428. {
  429. TCHAR szFormat[256];
  430. GetClipboardFormatName(cbType, szFormat, 256);
  431. return szFormat;
  432. }
  433. break;
  434. }
  435. return "ERROR";
  436. }
  437. CString GetFilePath(CString csFileName)
  438. {
  439. long lSlash = csFileName.ReverseFind('\\');
  440. if(lSlash > -1)
  441. {
  442. csFileName = csFileName.Left(lSlash + 1);
  443. }
  444. return csFileName;
  445. }
  446. /*------------------------------------------------------------------*\
  447. CGetSetOptions
  448. \*------------------------------------------------------------------*/
  449. long CGetSetOptions::m_nLinesPerRow;
  450. BOOL CGetSetOptions::m_bUseCtrlNumAccel;
  451. BOOL CGetSetOptions::m_bAllowDuplicates;
  452. BOOL CGetSetOptions::m_bUpdateTimeOnPaste;
  453. BOOL CGetSetOptions::m_bSaveMultiPaste;
  454. BOOL CGetSetOptions::m_bShowPersistent;
  455. BOOL CGetSetOptions::m_bHistoryStartTop;
  456. long CGetSetOptions::m_bDescTextSize;
  457. BOOL CGetSetOptions::m_bDescShowLeadingWhiteSpace;
  458. BOOL CGetSetOptions::m_bAllwaysShowDescription;
  459. long CGetSetOptions::m_bDoubleClickingOnCaptionDoes;
  460. BOOL CGetSetOptions::m_bPrompForNewGroupName;
  461. BOOL CGetSetOptions::m_bSendPasteOnFirstTenHotKeys;
  462. CSendClients CGetSetOptions::m_SendClients[MAX_SEND_CLIENTS];
  463. long CGetSetOptions::m_lAutoSendClientCount;
  464. CString CGetSetOptions::m_csIPListToPutOnClipboard;
  465. BOOL CGetSetOptions::m_bLogSendReceiveErrors;
  466. BOOL CGetSetOptions::m_bUseHookDllForFocus;
  467. BOOL CGetSetOptions::m_HideDittoOnHotKeyIfAlreadyShown;
  468. long CGetSetOptions::m_lPort;
  469. CGetSetOptions g_Opt;
  470. CGetSetOptions::CGetSetOptions()
  471. {
  472. m_nLinesPerRow = GetLinesPerRow();
  473. m_bUseCtrlNumAccel = GetUseCtrlNumForFirstTenHotKeys();
  474. m_bAllowDuplicates = GetAllowDuplicates();
  475. m_bUpdateTimeOnPaste = GetUpdateTimeOnPaste();
  476. m_bSaveMultiPaste = GetSaveMultiPaste();
  477. m_bShowPersistent = GetShowPersistent();
  478. m_bHistoryStartTop = GetHistoryStartTop();
  479. m_bDescTextSize = GetDescTextSize();
  480. m_bDescShowLeadingWhiteSpace = GetDescShowLeadingWhiteSpace();
  481. m_bAllwaysShowDescription = GetAllwaysShowDescription();
  482. m_bDoubleClickingOnCaptionDoes = GetDoubleClickingOnCaptionDoes();
  483. m_bPrompForNewGroupName = GetPrompForNewGroupName();
  484. m_bSendPasteOnFirstTenHotKeys = GetSendPasteOnFirstTenHotKeys();
  485. m_csIPListToPutOnClipboard = GetListToPutOnClipboard();
  486. m_bLogSendReceiveErrors = GetLogSendReceiveErrors();
  487. m_bUseHookDllForFocus = GetProfileLong("UseHookDllForFocus", TRUE);
  488. m_HideDittoOnHotKeyIfAlreadyShown = GetHideDittoOnHotKeyIfAlreadyShown();
  489. m_lPort = GetPort();
  490. #ifdef _DEBUG
  491. m_bUseHookDllForFocus = FALSE;
  492. #endif
  493. for(int i = 0; i < MAX_SEND_CLIENTS; i++)
  494. {
  495. GetSendClients(i);
  496. }
  497. GetClientSendCount();
  498. }
  499. CGetSetOptions::~CGetSetOptions()
  500. {
  501. }
  502. long CGetSetOptions::GetProfileLong(CString csName, long bDefaultValue)
  503. {
  504. HKEY hkKey;
  505. long lResult = RegOpenKeyEx(HKEY_CURRENT_USER, _T(REG_PATH),
  506. NULL, KEY_READ, &hkKey);
  507. if(lResult != ERROR_SUCCESS)
  508. return bDefaultValue;
  509. DWORD buffer;
  510. DWORD len = sizeof(buffer);
  511. DWORD type;
  512. lResult = ::RegQueryValueEx(hkKey, csName, 0, &type, (LPBYTE)&buffer, &len);
  513. RegCloseKey(hkKey);
  514. if(lResult == ERROR_SUCCESS)
  515. return (long)buffer;
  516. return bDefaultValue;
  517. }
  518. CString CGetSetOptions::GetProfileString(CString csName, CString csDefault)
  519. {
  520. HKEY hkKey;
  521. long lResult = RegOpenKeyEx(HKEY_CURRENT_USER, _T(REG_PATH),
  522. NULL, KEY_READ, &hkKey);
  523. char szString[256];
  524. DWORD dwBufLen = 256;
  525. lResult = ::RegQueryValueEx(hkKey , csName, NULL, NULL, (LPBYTE)szString, &dwBufLen);
  526. if(lResult != ERROR_SUCCESS)
  527. return csDefault;
  528. return CString(szString);
  529. }
  530. BOOL CGetSetOptions::SetProfileLong(CString csName, long lValue)
  531. {
  532. HKEY hkKey;
  533. DWORD dWord;
  534. long lResult = RegCreateKeyEx(HKEY_CURRENT_USER, _T(REG_PATH), NULL,
  535. NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  536. NULL, &hkKey, &dWord);
  537. if(lResult != ERROR_SUCCESS)
  538. return FALSE;
  539. DWORD val = (DWORD)lValue;
  540. lResult = ::RegSetValueEx(hkKey, csName, 0, REG_DWORD, (LPBYTE)&val, sizeof(DWORD));
  541. RegCloseKey(hkKey);
  542. return lResult == ERROR_SUCCESS;
  543. }
  544. BOOL CGetSetOptions::SetProfileString(CString csName, CString csValue)
  545. {
  546. HKEY hkKey;
  547. DWORD dWord;
  548. long lResult = RegCreateKeyEx(HKEY_CURRENT_USER, _T(REG_PATH), NULL,
  549. NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
  550. NULL, &hkKey, &dWord);
  551. if(lResult != ERROR_SUCCESS)
  552. return FALSE;
  553. ::RegSetValueEx(hkKey, csName, NULL, REG_SZ,
  554. (BYTE*)(LPCTSTR)csValue, csValue.GetLength()+sizeof(TCHAR));
  555. RegCloseKey(hkKey);
  556. return lResult == ERROR_SUCCESS;
  557. }
  558. BOOL CGetSetOptions::GetShowIconInSysTray()
  559. {
  560. return GetProfileLong("ShowIconInSystemTray", TRUE);
  561. }
  562. BOOL CGetSetOptions::SetShowIconInSysTray(BOOL bShow)
  563. {
  564. return SetProfileLong("ShowIconInSystemTray", bShow);
  565. }
  566. BOOL CGetSetOptions::SetEnableTransparency(BOOL bCheck)
  567. {
  568. return SetProfileLong("EnableTransparency", bCheck);
  569. }
  570. BOOL CGetSetOptions::GetEnableTransparency()
  571. {
  572. return GetProfileLong("EnableTransparency", FALSE);
  573. }
  574. BOOL CGetSetOptions::SetTransparencyPercent(long lPercent)
  575. {
  576. #ifdef AFTER_98
  577. if(lPercent > OPACITY_MAX)
  578. lPercent = OPACITY_MAX;
  579. if(lPercent < 0)
  580. lPercent = 0;
  581. return SetProfileLong("TransparencyPercent", lPercent);
  582. #endif
  583. return FALSE;
  584. }
  585. long CGetSetOptions::GetTransparencyPercent()
  586. {
  587. #ifdef AFTER_98
  588. long lValue = GetProfileLong("TransparencyPercent", 14);
  589. if(lValue > OPACITY_MAX) lValue = OPACITY_MAX;
  590. if(lValue < 0) lValue = 0;
  591. return lValue;
  592. #endif
  593. return 0;
  594. }
  595. BOOL CGetSetOptions::SetLinesPerRow(long lLines)
  596. {
  597. m_nLinesPerRow = lLines;
  598. return SetProfileLong("LinesPerRow", lLines);
  599. }
  600. long CGetSetOptions::GetLinesPerRow()
  601. {
  602. return GetProfileLong("LinesPerRow", 2);
  603. }
  604. BOOL CGetSetOptions::GetRunOnStartUp()
  605. {
  606. HKEY hkRun;
  607. LONG nResult = RegOpenKeyEx(HKEY_CURRENT_USER,
  608. _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"),
  609. NULL, KEY_READ, &hkRun);
  610. if(nResult != ERROR_SUCCESS)
  611. return FALSE;
  612. nResult = RegQueryValueEx(hkRun, GetAppName(), NULL, NULL, NULL, NULL);
  613. RegCloseKey(hkRun);
  614. return nResult == ERROR_SUCCESS;
  615. }
  616. void CGetSetOptions::SetRunOnStartUp(BOOL bRun)
  617. {
  618. if(bRun == GetRunOnStartUp())
  619. return;
  620. HKEY hkRun;
  621. LONG nResult = RegOpenKeyEx(HKEY_CURRENT_USER,
  622. _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"),
  623. NULL, KEY_ALL_ACCESS, &hkRun);
  624. if(nResult != ERROR_SUCCESS)
  625. return;
  626. if(bRun)
  627. {
  628. CString sExeName = GetExeFileName();
  629. ::RegSetValueEx(hkRun, GetAppName(), NULL, REG_SZ,
  630. (BYTE*)(LPCTSTR)sExeName, sExeName.GetLength()+sizeof(TCHAR));
  631. }
  632. else
  633. {
  634. ::RegDeleteValue(hkRun, GetAppName());
  635. }
  636. ::RegCloseKey(hkRun);
  637. }
  638. CString CGetSetOptions::GetExeFileName()
  639. {
  640. CString sExeName;
  641. GetModuleFileName(NULL, sExeName.GetBuffer(_MAX_PATH),_MAX_PATH);
  642. sExeName.ReleaseBuffer();
  643. return sExeName;
  644. }
  645. CString CGetSetOptions::GetAppName()
  646. {
  647. return "Ditto";
  648. }
  649. BOOL CGetSetOptions::SetQuickPastePosition(long lPosition)
  650. {
  651. return SetProfileLong("ShowQuickPastePosition", lPosition);
  652. }
  653. long CGetSetOptions::GetQuickPastePosition()
  654. {
  655. return GetProfileLong("ShowQuickPastePosition", POS_AT_PREVIOUS);
  656. }
  657. BOOL CGetSetOptions::SetQuickPasteSize(CSize size)
  658. {
  659. BOOL bRet = SetProfileLong("QuickPasteCX", size.cx);
  660. bRet = SetProfileLong("QuickPasteCY", size.cy);
  661. return bRet;
  662. }
  663. void CGetSetOptions::GetQuickPasteSize(CSize &size)
  664. {
  665. size.cx = GetProfileLong("QuickPasteCX", 300);
  666. size.cy = GetProfileLong("QuickPasteCY", 300);
  667. }
  668. BOOL CGetSetOptions::SetQuickPastePoint(CPoint point)
  669. {
  670. BOOL bRet = SetProfileLong("QuickPasteX", point.x);
  671. bRet = SetProfileLong("QuickPasteY", point.y);
  672. return bRet;
  673. }
  674. void CGetSetOptions::GetQuickPastePoint(CPoint &point)
  675. {
  676. point.x = GetProfileLong("QuickPasteX", 300);
  677. point.y = GetProfileLong("QuickPasteY", 300);
  678. }
  679. long CGetSetOptions::GetCopyGap()
  680. {
  681. return GetProfileLong("CopyGap", 150);
  682. }
  683. BOOL CGetSetOptions::SetDBPath(CString csPath)
  684. {
  685. return SetProfileString("DBPath", csPath);
  686. }
  687. CString CGetSetOptions::GetDBPath(BOOL bDefault/* = TRUE*/)
  688. {
  689. //First check the reg string
  690. CString csDefaultPath = GetProfileString("DBPath", "");
  691. //If there is nothing in the regesty then get the default
  692. //In the users application data in my documents
  693. if(bDefault)
  694. {
  695. if(csDefaultPath.IsEmpty())
  696. csDefaultPath = GetDefaultDBName();
  697. }
  698. return csDefaultPath;
  699. }
  700. void CGetSetOptions::SetCheckForMaxEntries(BOOL bVal)
  701. {
  702. SetProfileLong("CheckForMaxEntries", bVal);
  703. }
  704. BOOL CGetSetOptions::GetCheckForMaxEntries()
  705. {
  706. return GetProfileLong("CheckForMaxEntries", 0);
  707. }
  708. void CGetSetOptions::SetCheckForExpiredEntries(BOOL bVal)
  709. {
  710. SetProfileLong("CheckForExpiredEntries", bVal);
  711. }
  712. BOOL CGetSetOptions::GetCheckForExpiredEntries()
  713. {
  714. return GetProfileLong("CheckForExpiredEntries", 0);
  715. }
  716. void CGetSetOptions::SetMaxEntries(long lVal)
  717. {
  718. SetProfileLong("MaxEntries", lVal);
  719. }
  720. long CGetSetOptions::GetMaxEntries()
  721. {
  722. return GetProfileLong("MaxEntries", 500);
  723. }
  724. void CGetSetOptions::SetExpiredEntries(long lVal)
  725. {
  726. SetProfileLong("ExpiredEntries", lVal);
  727. }
  728. long CGetSetOptions::GetExpiredEntries()
  729. {
  730. return GetProfileLong("ExpiredEntries", 5);
  731. }
  732. void CGetSetOptions::SetTripCopyCount(long lVal)
  733. {
  734. // negative means a relative offset
  735. if(lVal < 0)
  736. lVal = GetTripCopyCount() - lVal; // add the absolute value
  737. if(GetTripDate() == 0)
  738. SetTripDate(-1);
  739. SetProfileLong("TripCopies", lVal);
  740. }
  741. long CGetSetOptions::GetTripCopyCount()
  742. {
  743. return GetProfileLong("TripCopies", 0);
  744. }
  745. void CGetSetOptions::SetTripPasteCount(long lVal)
  746. {
  747. // negative means a relative offset
  748. if(lVal < 0)
  749. lVal = GetTripPasteCount() - lVal; // add the absolute value
  750. if(GetTripDate() == 0)
  751. SetTripDate(-1);
  752. SetProfileLong("TripPastes", lVal);
  753. }
  754. long CGetSetOptions::GetTripPasteCount()
  755. {
  756. return GetProfileLong("TripPastes", 0);
  757. }
  758. void CGetSetOptions::SetTripDate(long lDate)
  759. {
  760. if(lDate == -1)
  761. lDate = (long)CTime::GetCurrentTime().GetTime();
  762. SetProfileLong("TripDate", lDate);
  763. }
  764. long CGetSetOptions::GetTripDate()
  765. {
  766. return GetProfileLong("TripDate", 0);
  767. }
  768. void CGetSetOptions::SetTotalCopyCount(long lVal)
  769. {
  770. // negative means a relative offset
  771. if(lVal < 0)
  772. lVal = GetTotalCopyCount() - lVal; // add the absolute value
  773. if(GetTotalDate() == 0)
  774. SetTotalDate(-1);
  775. SetProfileLong("TotalCopies", lVal);
  776. }
  777. long CGetSetOptions::GetTotalCopyCount()
  778. {
  779. return GetProfileLong("TotalCopies", 0);
  780. }
  781. void CGetSetOptions::SetTotalPasteCount(long lVal)
  782. {
  783. // negative means a relative offset
  784. if(lVal < 0)
  785. lVal = GetTotalPasteCount() - lVal; // add the absolute value
  786. if(GetTotalDate() == 0)
  787. SetTotalDate(-1);
  788. SetProfileLong("TotalPastes", lVal);
  789. }
  790. long CGetSetOptions::GetTotalPasteCount()
  791. {
  792. return GetProfileLong("TotalPastes", 0);
  793. }
  794. void CGetSetOptions::SetTotalDate(long lDate)
  795. {
  796. if(lDate == -1)
  797. lDate = (long)CTime::GetCurrentTime().GetTime();
  798. SetProfileLong("TotalDate", lDate);
  799. }
  800. long CGetSetOptions::GetTotalDate()
  801. {
  802. return GetProfileLong("TotalDate", 0);
  803. }
  804. void CGetSetOptions::SetCompactAndRepairOnExit(BOOL bVal)
  805. {
  806. SetProfileLong("CompactAndRepairOnExit", bVal);
  807. }
  808. BOOL CGetSetOptions::GetCompactAndRepairOnExit()
  809. {
  810. return GetProfileLong("CompactAndRepairOnExit", 0);
  811. }
  812. // the implementations for the following functions were moved out-of-line.
  813. // when they were declared inline, the compiler failed to notice when
  814. // these functions were changed (the linker used an old compiled version)
  815. // (maybe because they are also static?)
  816. CString CGetSetOptions::GetUpdateFilePath() { return GetProfileString("UpdateFilePath", ""); }
  817. BOOL CGetSetOptions::SetUpdateFilePath(CString cs) { return SetProfileString("UpdateFilePath", cs); }
  818. CString CGetSetOptions::GetUpdateInstallPath() { return GetProfileString("UpdateInstallPath", ""); }
  819. BOOL CGetSetOptions::SetUpdateInstallPath(CString cs) { return SetProfileString("UpdateInstallPath", cs); }
  820. long CGetSetOptions::GetLastUpdate() { return GetProfileLong("LastUpdateDay", 0); }
  821. long CGetSetOptions::SetLastUpdate(long lValue) { return SetProfileLong("LastUpdateDay", lValue); }
  822. BOOL CGetSetOptions::GetCheckForUpdates() { return GetProfileLong("CheckForUpdates", TRUE); }
  823. BOOL CGetSetOptions::SetCheckForUpdates(BOOL bCheck) { return SetProfileLong("CheckForUpdates", bCheck); }
  824. void CGetSetOptions::SetUseCtrlNumForFirstTenHotKeys(BOOL bVal) { SetProfileLong("UseCtrlNumForFirstTenHotKeys", bVal); m_bUseCtrlNumAccel = bVal; }
  825. BOOL CGetSetOptions::GetUseCtrlNumForFirstTenHotKeys() { return GetProfileLong("UseCtrlNumForFirstTenHotKeys", 0); }
  826. void CGetSetOptions::SetAllowDuplicates(BOOL bVal) { SetProfileLong("AllowDuplicates", bVal); m_bAllowDuplicates = bVal; }
  827. BOOL CGetSetOptions::GetAllowDuplicates() { return GetProfileLong("AllowDuplicates", 0); }
  828. void CGetSetOptions::SetUpdateTimeOnPaste(BOOL bVal) { SetProfileLong("UpdateTimeOnPaste", bVal); m_bUpdateTimeOnPaste = bVal; }
  829. BOOL CGetSetOptions::GetUpdateTimeOnPaste() { return GetProfileLong("UpdateTimeOnPaste", TRUE); }
  830. void CGetSetOptions::SetSaveMultiPaste(BOOL bVal) { SetProfileLong("SaveMultiPaste", bVal); m_bSaveMultiPaste = bVal; }
  831. BOOL CGetSetOptions::GetSaveMultiPaste() { return GetProfileLong("SaveMultiPaste", 0); }
  832. void CGetSetOptions::SetShowPersistent(BOOL bVal) { SetProfileLong("ShowPersistent", bVal); m_bShowPersistent = bVal; }
  833. BOOL CGetSetOptions::GetShowPersistent() { return GetProfileLong("ShowPersistent", 0); }
  834. void CGetSetOptions::SetHistoryStartTop(BOOL bVal) { SetProfileLong("HistoryStartTop", bVal); m_bHistoryStartTop = bVal; }
  835. BOOL CGetSetOptions::GetHistoryStartTop() { return GetProfileLong("HistoryStartTop", TRUE); }
  836. void CGetSetOptions::SetShowTextForFirstTenHotKeys(BOOL bVal) { SetProfileLong("ShowTextForFirstTenHotKeys", bVal); }
  837. BOOL CGetSetOptions::GetShowTextForFirstTenHotKeys() { return GetProfileLong("ShowTextForFirstTenHotKeys", TRUE); }
  838. void CGetSetOptions::SetMainHWND(long lhWnd) { SetProfileLong("MainhWnd", lhWnd); }
  839. BOOL CGetSetOptions::GetMainHWND() { return GetProfileLong("MainhWnd", 0); }
  840. void CGetSetOptions::SetCaptionPos(long lPos) { SetProfileLong("CaptionPos", lPos); }
  841. long CGetSetOptions::GetCaptionPos() { return GetProfileLong("CaptionPos", CAPTION_RIGHT); }
  842. void CGetSetOptions::SetAutoHide(BOOL bAutoHide){ SetProfileLong("AutoHide", bAutoHide); }
  843. BOOL CGetSetOptions::GetAutoHide() { return GetProfileLong("AutoHide", FALSE); }
  844. void CGetSetOptions::SetDescTextSize(long lSize){ SetProfileLong("DescTextSize", lSize); m_bDescTextSize = lSize; }
  845. long CGetSetOptions::GetDescTextSize() { return GetProfileLong("DescTextSize", 500); }
  846. void CGetSetOptions::SetDescShowLeadingWhiteSpace(BOOL bVal){ SetProfileLong("DescShowLeadingWhiteSpace", bVal); m_bDescShowLeadingWhiteSpace = bVal; }
  847. BOOL CGetSetOptions::GetDescShowLeadingWhiteSpace() { return GetProfileLong("DescShowLeadingWhiteSpace", FALSE); }
  848. void CGetSetOptions::SetAllwaysShowDescription(long bShow) { SetProfileLong("AllwaysShowDescription", bShow); m_bAllwaysShowDescription = bShow; }
  849. BOOL CGetSetOptions::GetAllwaysShowDescription() { return GetProfileLong("AllwaysShowDescription", FALSE); }
  850. void CGetSetOptions::SetDoubleClickingOnCaptionDoes(long lOption) { SetProfileLong("DoubleClickingOnCaptionDoes", lOption); m_bDoubleClickingOnCaptionDoes = lOption; }
  851. long CGetSetOptions::GetDoubleClickingOnCaptionDoes() { return GetProfileLong("DoubleClickingOnCaptionDoes", TOGGLES_ALLWAYS_ON_TOP); }
  852. void CGetSetOptions::SetPrompForNewGroupName(BOOL bOption) { SetProfileLong("PrompForNewGroupName", bOption); m_bPrompForNewGroupName = bOption; }
  853. BOOL CGetSetOptions::GetPrompForNewGroupName() { return GetProfileLong("PrompForNewGroupName", TRUE); }
  854. void CGetSetOptions::SetSendPasteOnFirstTenHotKeys(BOOL bOption) { SetProfileLong("SendPasteOnFirstTenHotKeys", bOption); m_bSendPasteOnFirstTenHotKeys = bOption; }
  855. BOOL CGetSetOptions::GetSendPasteOnFirstTenHotKeys() { return GetProfileLong("SendPasteOnFirstTenHotKeys", TRUE); }
  856. void CGetSetOptions::SetSendClients(CSendClients Client, int nPos)
  857. {
  858. CString cs;
  859. cs.Format("sendclient_ip_%d", nPos);
  860. SetProfileString(cs, Client.csIP);
  861. cs.Format("sendclient_autosend_%d", nPos);
  862. SetProfileLong(cs, Client.bSendAll);
  863. cs.Format("sendclient_description_%d", nPos);
  864. SetProfileString(cs, Client.csDescription);
  865. m_SendClients[nPos] = Client;
  866. }
  867. CSendClients CGetSetOptions::GetSendClients(int nPos)
  868. {
  869. CSendClients Client;
  870. CString cs;
  871. cs.Format("sendclient_ip_%d", nPos);
  872. Client.csIP = GetProfileString(cs, "");
  873. cs.Format("sendclient_autosend_%d", nPos);
  874. Client.bSendAll = GetProfileLong(cs, FALSE);
  875. cs.Format("sendclient_description_%d", nPos);
  876. Client.csDescription = GetProfileString(cs, "");
  877. m_SendClients[nPos] = Client;
  878. return Client;
  879. }
  880. void CGetSetOptions::GetClientSendCount()
  881. {
  882. m_lAutoSendClientCount = 0;
  883. for(int i = 0; i < MAX_SEND_CLIENTS; i++)
  884. {
  885. if(m_SendClients[i].csIP.GetLength() > 0)
  886. {
  887. if(m_SendClients[i].bSendAll)
  888. m_lAutoSendClientCount++;
  889. }
  890. }
  891. }
  892. CString CGetSetOptions::GetListToPutOnClipboard()
  893. {
  894. CString cs = GetProfileString("ListToPutOnClipboard", "");
  895. cs.MakeUpper();
  896. return cs;
  897. }
  898. BOOL CGetSetOptions::SetListToPutOnClipboard(CString cs)
  899. {
  900. cs.MakeUpper();
  901. m_csIPListToPutOnClipboard = cs;
  902. return SetProfileString("ListToPutOnClipboard", cs);
  903. }
  904. void CGetSetOptions::SetLogSendReceiveErrors(BOOL bOption)
  905. {
  906. m_bLogSendReceiveErrors = bOption;
  907. SetProfileLong("LogSendReceiveErrors", bOption);
  908. }
  909. BOOL CGetSetOptions::GetLogSendReceiveErrors()
  910. {
  911. return GetProfileLong("LogSendReceiveErrors", FALSE);
  912. }
  913. BOOL CGetSetOptions::GetHideDittoOnHotKeyIfAlreadyShown()
  914. {
  915. return GetProfileLong("HideDittoOnHotKeyIfAlreadyShown", TRUE);
  916. }
  917. void CGetSetOptions::SetHideDittoOnHotKeyIfAlreadyShown(BOOL bVal)
  918. {
  919. m_HideDittoOnHotKeyIfAlreadyShown = bVal;
  920. SetProfileLong("HideDittoOnHotKeyIfAlreadyShown", bVal);
  921. }
  922. void CGetSetOptions::SetPort(long lPort)
  923. {
  924. m_lPort = lPort;
  925. SetProfileLong("SendRecvPort", lPort);
  926. }
  927. long CGetSetOptions::GetPort()
  928. {
  929. return GetProfileLong("SendRecvPort", 23443);
  930. }
  931. BOOL CGetSetOptions::GetDisableRecieve()
  932. {
  933. return GetProfileLong("DisableRecieve", FALSE);
  934. }
  935. void CGetSetOptions::SetDisableRecieve(BOOL bVal)
  936. {
  937. SetProfileLong("DisableRecieve", bVal);
  938. }
  939. /*------------------------------------------------------------------*\
  940. CHotKey - a single system-wide hotkey
  941. \*------------------------------------------------------------------*/
  942. CHotKey::CHotKey( CString name, DWORD defKey, bool bUnregOnShowDitto )
  943. : m_Name(name), m_bIsRegistered(false), m_bUnRegisterOnShowDitto(bUnregOnShowDitto)
  944. {
  945. m_Atom = ::GlobalAddAtom( m_Name );
  946. ASSERT( m_Atom );
  947. m_Key = (DWORD) g_Opt.GetProfileLong( m_Name, (long) defKey );
  948. g_HotKeys.Add( this );
  949. }
  950. CHotKey::~CHotKey()
  951. {
  952. Unregister();
  953. }
  954. void CHotKey::SetKey( DWORD key, bool bSave )
  955. {
  956. if( m_Key == key )
  957. return;
  958. if( m_bIsRegistered )
  959. Unregister();
  960. m_Key = key;
  961. if( bSave )
  962. SaveKey();
  963. }
  964. void CHotKey::LoadKey()
  965. {
  966. SetKey( (DWORD) g_Opt.GetProfileLong( m_Name, 0 ) );
  967. }
  968. bool CHotKey::SaveKey()
  969. {
  970. return g_Opt.SetProfileLong( m_Name, (long) m_Key ) != FALSE;
  971. }
  972. // CString GetKeyAsText();
  973. // void SetKeyFromText( CString text );
  974. BOOL CHotKey::ValidateHotKey(DWORD dwHotKey)
  975. {
  976. ATOM id = ::GlobalAddAtom("HK_VALIDATE");
  977. BOOL bResult = ::RegisterHotKey( g_HotKeys.m_hWnd,
  978. id,
  979. GetModifier(dwHotKey),
  980. LOBYTE(dwHotKey) );
  981. if(bResult)
  982. ::UnregisterHotKey(g_HotKeys.m_hWnd, id);
  983. ::GlobalDeleteAtom(id);
  984. return bResult;
  985. }
  986. UINT CHotKey::GetModifier(DWORD dwHotKey)
  987. {
  988. UINT uMod = 0;
  989. if( HIBYTE(dwHotKey) & HOTKEYF_SHIFT ) uMod |= MOD_SHIFT;
  990. if( HIBYTE(dwHotKey) & HOTKEYF_CONTROL ) uMod |= MOD_CONTROL;
  991. if( HIBYTE(dwHotKey) & HOTKEYF_ALT ) uMod |= MOD_ALT;
  992. if( HIBYTE(dwHotKey) & HOTKEYF_EXT ) uMod |= MOD_WIN;
  993. return uMod;
  994. }
  995. bool CHotKey::Register()
  996. {
  997. if( m_Key )
  998. {
  999. if(m_bIsRegistered == false)
  1000. {
  1001. ASSERT( g_HotKeys.m_hWnd );
  1002. m_bIsRegistered = ::RegisterHotKey( g_HotKeys.m_hWnd,
  1003. m_Atom,
  1004. GetModifier(),
  1005. LOBYTE(m_Key) ) == TRUE;
  1006. }
  1007. }
  1008. else
  1009. m_bIsRegistered = true;
  1010. return m_bIsRegistered;
  1011. }
  1012. bool CHotKey::Unregister(bool bOnShowingDitto)
  1013. {
  1014. if( !m_bIsRegistered )
  1015. return true;
  1016. if(bOnShowingDitto)
  1017. {
  1018. if(m_bUnRegisterOnShowDitto == false)
  1019. return true;
  1020. }
  1021. if(m_Key)
  1022. {
  1023. ASSERT(g_HotKeys.m_hWnd);
  1024. if( ::UnregisterHotKey( g_HotKeys.m_hWnd, m_Atom ) )
  1025. {
  1026. m_bIsRegistered = false;
  1027. return true;
  1028. }
  1029. else
  1030. {
  1031. LOG("Unregister" "FAILED!");
  1032. ASSERT(0);
  1033. }
  1034. }
  1035. else
  1036. {
  1037. m_bIsRegistered = false;
  1038. return true;
  1039. }
  1040. return false;
  1041. }
  1042. /*------------------------------------------------------------------*\
  1043. CHotKeys - Manages system-wide hotkeys
  1044. \*------------------------------------------------------------------*/
  1045. CHotKeys g_HotKeys;
  1046. CHotKeys::CHotKeys() : m_hWnd(NULL) {}
  1047. CHotKeys::~CHotKeys()
  1048. {
  1049. CHotKey* pHotKey;
  1050. int count = GetSize();
  1051. for( int i=0; i < count; i++ )
  1052. {
  1053. pHotKey = ElementAt(i);
  1054. if( pHotKey )
  1055. delete pHotKey;
  1056. }
  1057. }
  1058. int CHotKeys::Find( CHotKey* pHotKey )
  1059. {
  1060. int count = GetSize();
  1061. for( int i=0; i < count; i++ )
  1062. {
  1063. if( pHotKey == ElementAt(i) )
  1064. return i;
  1065. }
  1066. return -1;
  1067. }
  1068. bool CHotKeys::Remove( CHotKey* pHotKey )
  1069. {
  1070. int i = Find(pHotKey);
  1071. if( i >= 0 )
  1072. {
  1073. RemoveAt(i);
  1074. return true;
  1075. }
  1076. return false;
  1077. }
  1078. void CHotKeys::LoadAllKeys()
  1079. {
  1080. int count = GetSize();
  1081. for( int i=0; i < count; i++ )
  1082. ElementAt(i)->LoadKey();
  1083. }
  1084. void CHotKeys::SaveAllKeys()
  1085. {
  1086. int count = GetSize();
  1087. for( int i=0; i < count; i++ )
  1088. ElementAt(i)->SaveKey();
  1089. }
  1090. void CHotKeys::RegisterAll( bool bMsgOnError )
  1091. {
  1092. CString str;
  1093. CHotKey* pHotKey;
  1094. int count = GetSize();
  1095. for( int i=0; i < count; i++ )
  1096. {
  1097. pHotKey = ElementAt(i);
  1098. if( !pHotKey->Register() )
  1099. {
  1100. str = "Error Registering ";
  1101. str += pHotKey->GetName();
  1102. LOG( str );
  1103. if( bMsgOnError )
  1104. AfxMessageBox(str);
  1105. }
  1106. }
  1107. }
  1108. void CHotKeys::UnregisterAll(bool bMsgOnError, bool bOnShowDitto)
  1109. {
  1110. CString str;
  1111. CHotKey* pHotKey;
  1112. int count = GetSize();
  1113. for( int i=0; i < count; i++ )
  1114. {
  1115. pHotKey = ElementAt(i);
  1116. if(!pHotKey->Unregister(bOnShowDitto))
  1117. {
  1118. str = "Error Unregistering ";
  1119. str += pHotKey->GetName();
  1120. LOG( str );
  1121. if( bMsgOnError )
  1122. AfxMessageBox(str);
  1123. }
  1124. }
  1125. }
  1126. void CHotKeys::GetKeys( ARRAY& keys )
  1127. {
  1128. int count = GetSize();
  1129. keys.SetSize( count );
  1130. for( int i=0; i < count; i++ )
  1131. keys[i] = ElementAt(i)->GetKey();
  1132. }
  1133. // caution! this alters hotkeys based upon corresponding indexes
  1134. void CHotKeys::SetKeys( ARRAY& keys, bool bSave )
  1135. {
  1136. int count = GetSize();
  1137. ASSERT( count == keys.GetSize() );
  1138. for( int i=0; i < count; i++ )
  1139. ElementAt(i)->SetKey( keys[i], bSave );
  1140. }
  1141. bool CHotKeys::FindFirstConflict( ARRAY& keys, int* pX, int* pY )
  1142. {
  1143. bool bConflict = false;
  1144. int i, j;
  1145. int count = keys.GetSize();
  1146. DWORD key;
  1147. for( i=0; i < count && !bConflict; i++ )
  1148. {
  1149. key = keys.ElementAt(i);
  1150. // only check valid keys
  1151. if( key == 0 )
  1152. continue;
  1153. // scan the array for a duplicate
  1154. for( j=i+1; j < count; j++ )
  1155. {
  1156. if( keys.ElementAt(j) == key )
  1157. {
  1158. bConflict = true;
  1159. break;
  1160. }
  1161. }
  1162. }
  1163. if( bConflict )
  1164. {
  1165. if( pX )
  1166. *pX = i-1;
  1167. if( pY )
  1168. *pY = j;
  1169. }
  1170. return bConflict;
  1171. }
  1172. // if true, pX and pY (if valid) are set to the indexes of the conflicting hotkeys.
  1173. bool CHotKeys::FindFirstConflict( int* pX, int* pY )
  1174. {
  1175. ARRAY keys;
  1176. GetKeys( keys );
  1177. return FindFirstConflict( keys, pX, pY );
  1178. }
  1179. /****************************************************************************************************
  1180. BOOL CALLBACK MyMonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
  1181. ***************************************************************************************************/
  1182. typedef struct
  1183. {
  1184. long lFlags; // Flags
  1185. LPRECT pVirtualRect; // Ptr to rect that receives the results, or the src of the monitor search method
  1186. int iMonitor; // Ndx to the mointor to look at, -1 for all, -or- result of the monitor search method
  1187. int nMonitorCount; // Total number of monitors found, -1 for monitor search method
  1188. } MONITOR_ENUM_PARAM;
  1189. #define MONITOR_SEARCH_METOHD 0x00000001
  1190. BOOL CALLBACK MyMonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
  1191. {
  1192. // Typecast param
  1193. MONITOR_ENUM_PARAM* pParam = (MONITOR_ENUM_PARAM*)dwData;
  1194. if(pParam)
  1195. {
  1196. // If a dest rect was passed
  1197. if(pParam->pVirtualRect)
  1198. {
  1199. // If MONITOR_SEARCH_METOHD then we are being asked for the index of the monitor
  1200. // that the rect falls inside of
  1201. if(pParam->lFlags & MONITOR_SEARCH_METOHD)
  1202. {
  1203. if( (pParam->pVirtualRect->right < lprcMonitor->left) ||
  1204. (pParam->pVirtualRect->left > lprcMonitor->right) ||
  1205. (pParam->pVirtualRect->bottom < lprcMonitor->top) ||
  1206. (pParam->pVirtualRect->top > lprcMonitor->bottom))
  1207. {
  1208. // Nothing
  1209. }
  1210. else
  1211. {
  1212. // This is the one
  1213. pParam->iMonitor = pParam->nMonitorCount;
  1214. // Stop the enumeration
  1215. return FALSE;
  1216. }
  1217. }
  1218. else
  1219. {
  1220. if(pParam->iMonitor == pParam->nMonitorCount)
  1221. {
  1222. *pParam->pVirtualRect = *lprcMonitor;
  1223. }
  1224. else
  1225. if(pParam->iMonitor == -1)
  1226. {
  1227. pParam->pVirtualRect->left = min(pParam->pVirtualRect->left, lprcMonitor->left);
  1228. pParam->pVirtualRect->top = min(pParam->pVirtualRect->top, lprcMonitor->top);
  1229. pParam->pVirtualRect->right = max(pParam->pVirtualRect->right, lprcMonitor->right);
  1230. pParam->pVirtualRect->bottom = max(pParam->pVirtualRect->bottom, lprcMonitor->bottom);
  1231. }
  1232. }
  1233. }
  1234. // Up the count if necessary
  1235. pParam->nMonitorCount++;
  1236. }
  1237. return TRUE;
  1238. }
  1239. int GetScreenWidth(void)
  1240. {
  1241. OSVERSIONINFO OS_Version_Info;
  1242. DWORD dwPlatform = 0;
  1243. if(GetVersionEx(&OS_Version_Info) != 0)
  1244. {
  1245. dwPlatform = OS_Version_Info.dwPlatformId;
  1246. }
  1247. if(dwPlatform == VER_PLATFORM_WIN32_NT)
  1248. {
  1249. int width, height;
  1250. width = GetSystemMetrics(SM_CXSCREEN);
  1251. height = GetSystemMetrics(SM_CYSCREEN);
  1252. switch(width)
  1253. {
  1254. default:
  1255. case 640:
  1256. case 800:
  1257. case 1024:
  1258. return(width);
  1259. case 1280:
  1260. if(height == 480)
  1261. {
  1262. return(width / 2);
  1263. }
  1264. return(width);
  1265. case 1600:
  1266. if(height == 600)
  1267. {
  1268. return(width / 2);
  1269. }
  1270. return(width);
  1271. case 2048:
  1272. if(height == 768)
  1273. {
  1274. return(width / 2);
  1275. }
  1276. return(width);
  1277. }
  1278. }
  1279. else
  1280. {
  1281. return(GetSystemMetrics(SM_CXSCREEN));
  1282. }
  1283. }
  1284. int GetScreenHeight(void)
  1285. {
  1286. OSVERSIONINFO OS_Version_Info;
  1287. DWORD dwPlatform = 0;
  1288. if(GetVersionEx(&OS_Version_Info) != 0)
  1289. {
  1290. dwPlatform = OS_Version_Info.dwPlatformId;
  1291. }
  1292. if(dwPlatform == VER_PLATFORM_WIN32_NT)
  1293. {
  1294. int width, height;
  1295. width = GetSystemMetrics(SM_CXSCREEN);
  1296. height = GetSystemMetrics(SM_CYSCREEN);
  1297. switch(height)
  1298. {
  1299. default:
  1300. case 480:
  1301. case 600:
  1302. case 768:
  1303. return(height);
  1304. case 960:
  1305. if(width == 640)
  1306. {
  1307. return(height / 2);
  1308. }
  1309. return(height);
  1310. case 1200:
  1311. if(width == 800)
  1312. {
  1313. return(height / 2);
  1314. }
  1315. return(height);
  1316. case 1536:
  1317. if(width == 1024)
  1318. {
  1319. return(height / 2);
  1320. }
  1321. return(height);
  1322. }
  1323. }
  1324. else
  1325. {
  1326. return(GetSystemMetrics(SM_CYSCREEN));
  1327. }
  1328. }
  1329. int GetMonitorFromRect(LPRECT lpMonitorRect)
  1330. {
  1331. // Build up the param
  1332. MONITOR_ENUM_PARAM EnumParam;
  1333. ZeroMemory(&EnumParam, sizeof(EnumParam));
  1334. EnumParam.lFlags = MONITOR_SEARCH_METOHD;
  1335. EnumParam.pVirtualRect = lpMonitorRect;
  1336. EnumParam.iMonitor = -1;
  1337. // Enum Displays
  1338. EnumDisplayMonitors(NULL, NULL, MyMonitorEnumProc, (long)&EnumParam);
  1339. // Return the result
  1340. return EnumParam.iMonitor;
  1341. }
  1342. void GetMonitorRect(int iMonitor, LPRECT lpDestRect)
  1343. {
  1344. // Build up the param
  1345. MONITOR_ENUM_PARAM EnumParam;
  1346. ZeroMemory(&EnumParam, sizeof(EnumParam));
  1347. EnumParam.iMonitor = iMonitor;
  1348. EnumParam.pVirtualRect = lpDestRect;
  1349. // Zero out dest rect
  1350. lpDestRect->bottom = lpDestRect->left = lpDestRect->right = lpDestRect->top = 0;
  1351. // Enum Displays
  1352. EnumDisplayMonitors(NULL, NULL, MyMonitorEnumProc, (long)&EnumParam);
  1353. // If not successful, default to the screen dimentions
  1354. if(lpDestRect->right == 0 || lpDestRect->bottom == 0)
  1355. {
  1356. lpDestRect->right = GetScreenWidth();
  1357. lpDestRect->bottom = GetScreenHeight();
  1358. }
  1359. }
  1360. /*------------------------------------------------------------------*\
  1361. CAccel - an Accelerator (in-app hotkey)
  1362. - the win32 CreateAcceleratorTable using ACCEL was insufficient
  1363. because it only allowed a WORD for the cmd associated with it.
  1364. \*------------------------------------------------------------------*/
  1365. /*------------------------------------------------------------------*\
  1366. CAccels - Manages a set of CAccel
  1367. \*------------------------------------------------------------------*/
  1368. int CompareAccel( const void* pLeft, const void* pRight )
  1369. {
  1370. WORD w;
  1371. int l,r;
  1372. // swap bytes: place the VirtualKey in the MSB and the modifier in the LSB
  1373. // so that Accels based upon the same vkey are grouped together.
  1374. // this is required by our use of m_Index
  1375. // alternatively, we could store them this way in CAccel.
  1376. w = (WORD) ((CAccel*)pLeft)->Key;
  1377. l = (ACCEL_VKEY(w) << 8) | ACCEL_MOD(w);
  1378. w = (WORD) ((CAccel*)pRight)->Key;
  1379. r = (ACCEL_VKEY(w) << 8) | ACCEL_MOD(w);
  1380. return l - r;
  1381. }
  1382. CAccels::CAccels()
  1383. {}
  1384. void CAccels::AddAccel( CAccel& a )
  1385. {
  1386. m_Map.SetAt(a.Key, a.Cmd);
  1387. }
  1388. bool CAccels::OnMsg( MSG* pMsg, DWORD &dID)
  1389. {
  1390. // bit 30 (0x40000000) is 1 if this is NOT the first msg of the key
  1391. // i.e. auto-repeat may cause multiple msgs of the same key
  1392. if( (pMsg->lParam & 0x40000000) ||
  1393. (pMsg->message != WM_KEYDOWN &&
  1394. pMsg->message != WM_SYSKEYDOWN) )
  1395. {
  1396. return NULL;
  1397. }
  1398. if( !pMsg || m_Map.GetCount() <= 0 )
  1399. return NULL;
  1400. BYTE vkey = LOBYTE(pMsg->wParam);
  1401. BYTE mod = GetKeyStateModifiers();
  1402. DWORD key = ACCEL_MAKEKEY( vkey, mod );
  1403. if(m_Map.Lookup(key, dID))
  1404. return true;;
  1405. return false;
  1406. }
  1407. BYTE GetKeyStateModifiers()
  1408. {
  1409. BYTE m=0;
  1410. if( GetKeyState(VK_SHIFT) & 0x8000 )
  1411. m |= HOTKEYF_SHIFT;
  1412. if( GetKeyState(VK_CONTROL) & 0x8000 )
  1413. m |= HOTKEYF_CONTROL;
  1414. if( GetKeyState(VK_MENU) & 0x8000 )
  1415. m |= HOTKEYF_ALT;
  1416. return m;
  1417. }
  1418. /*------------------------------------------------------------------*\
  1419. CTokenizer - Tokenizes a string using given delimiters
  1420. \*------------------------------------------------------------------*/
  1421. CTokenizer::CTokenizer(const CString& cs, const CString& csDelim):
  1422. m_cs(cs),
  1423. m_nCurPos(0)
  1424. {
  1425. SetDelimiters(csDelim);
  1426. }
  1427. void CTokenizer::SetDelimiters(const CString& csDelim)
  1428. {
  1429. for(int i = 0; i < csDelim.GetLength(); ++i)
  1430. m_delim.set(static_cast<BYTE>(csDelim[i]));
  1431. }
  1432. bool CTokenizer::Next(CString& cs)
  1433. {
  1434. int len = m_cs.GetLength();
  1435. cs.Empty();
  1436. while(m_nCurPos < len && m_delim[static_cast<BYTE>(m_cs[m_nCurPos])])
  1437. ++m_nCurPos;
  1438. if(m_nCurPos >= len)
  1439. return false;
  1440. int nStartPos = m_nCurPos;
  1441. while(m_nCurPos < len && !m_delim[static_cast<BYTE>(m_cs[m_nCurPos])])
  1442. ++m_nCurPos;
  1443. cs = m_cs.Mid(nStartPos, m_nCurPos - nStartPos);
  1444. return true;
  1445. }
  1446. CString CTokenizer::Tail() const
  1447. {
  1448. int len = m_cs.GetLength();
  1449. int nCurPos = m_nCurPos;
  1450. while(nCurPos < len && m_delim[static_cast<BYTE>(m_cs[nCurPos])])
  1451. ++nCurPos;
  1452. CString csResult;
  1453. if(nCurPos < len)
  1454. csResult = m_cs.Mid(nCurPos);
  1455. return csResult;
  1456. }
  1457. /*------------------------------------------------------------------*\
  1458. Global ToolTip Manual Control Functions
  1459. \*------------------------------------------------------------------*/
  1460. void InitToolInfo( TOOLINFO& ti )
  1461. {
  1462. // INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE
  1463. ti.cbSize = sizeof(TOOLINFO);
  1464. ti.uFlags = TTF_ABSOLUTE | TTF_TRACK;
  1465. ti.hwnd = NULL;
  1466. ti.hinst = NULL;
  1467. ti.uId = 0; // CPopup only uses uid 0
  1468. ti.lpszText = NULL;
  1469. // ToolTip control will cover the whole window
  1470. ti.rect.left = 0;
  1471. ti.rect.top = 0;
  1472. ti.rect.right = 0;
  1473. ti.rect.bottom = 0;
  1474. }
  1475. /*------------------------------------------------------------------*\
  1476. CPopup - a tooltip that pops up manually (when Show is called).
  1477. - technique learned from codeproject "ToolTipZen" by "Zarembo Maxim"
  1478. \*------------------------------------------------------------------*/
  1479. CPopup::CPopup()
  1480. {
  1481. Init();
  1482. }
  1483. // HWND_TOP
  1484. CPopup::CPopup( int x, int y, HWND hWndPosRelativeTo, HWND hWndInsertAfter )
  1485. {
  1486. Init();
  1487. m_hWndPosRelativeTo = hWndPosRelativeTo;
  1488. m_hWndInsertAfter = hWndInsertAfter;
  1489. SetPos( CPoint(x,y) );
  1490. }
  1491. CPopup::~CPopup()
  1492. {
  1493. Hide();
  1494. if( m_bOwnTT && ::IsWindow(m_hTTWnd) )
  1495. ::DestroyWindow( m_hTTWnd );
  1496. }
  1497. void CPopup::Init()
  1498. {
  1499. // initialize variables
  1500. m_bOwnTT = false;
  1501. m_hTTWnd = NULL;
  1502. m_bIsShowing = false;
  1503. m_bAllowShow = true; // used by AllowShow()
  1504. m_Pos.x = m_Pos.y = 0;
  1505. m_bTop = true;
  1506. m_bLeft = true;
  1507. m_bCenterX = false;
  1508. m_bCenterY = false;
  1509. m_hWndPosRelativeTo = NULL;
  1510. RECT rcScreen;
  1511. GetMonitorRect(-1, &rcScreen);
  1512. m_ScreenMaxX = rcScreen.right;
  1513. m_ScreenMaxY = rcScreen.bottom;
  1514. m_hWndInsertAfter = HWND_TOP; //HWND_TOPMOST
  1515. SetTTWnd();
  1516. }
  1517. void CPopup::SetTTWnd( HWND hTTWnd, TOOLINFO* pTI )
  1518. {
  1519. if( pTI )
  1520. m_TI = *pTI;
  1521. else
  1522. InitToolInfo( m_TI );
  1523. if( m_bOwnTT && ::IsWindow(m_hTTWnd) )
  1524. {
  1525. if( !::IsWindow(hTTWnd) )
  1526. return; // we would have to recreate the one that already exists
  1527. ::DestroyWindow( m_hTTWnd );
  1528. }
  1529. m_hTTWnd = hTTWnd;
  1530. if( ::IsWindow(m_hTTWnd) )
  1531. {
  1532. m_bOwnTT = false;
  1533. // if our uid tooltip already exists, get the data, else add it.
  1534. if( ! ::SendMessage(m_hTTWnd, TTM_GETTOOLINFO, 0, (LPARAM)(LPTOOLINFO) &m_TI) )
  1535. ::SendMessage(m_hTTWnd, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &m_TI);
  1536. }
  1537. else
  1538. {
  1539. m_bOwnTT = true;
  1540. CreateToolTip();
  1541. }
  1542. }
  1543. void CPopup::CreateToolTip()
  1544. {
  1545. if( m_hTTWnd != NULL )
  1546. return;
  1547. // CREATE A TOOLTIP WINDOW
  1548. m_hTTWnd = CreateWindowEx(
  1549. WS_EX_TOPMOST,
  1550. TOOLTIPS_CLASS,
  1551. NULL,
  1552. TTS_NOPREFIX | TTS_ALWAYSTIP,
  1553. CW_USEDEFAULT,
  1554. CW_USEDEFAULT,
  1555. CW_USEDEFAULT,
  1556. CW_USEDEFAULT,
  1557. NULL,
  1558. NULL,
  1559. NULL,
  1560. NULL
  1561. );
  1562. m_bOwnTT = true;
  1563. // SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW
  1564. ::SendMessage(m_hTTWnd, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &m_TI);
  1565. }
  1566. void CPopup::SetTimeout( int timeout )
  1567. {
  1568. if( m_hTTWnd == NULL )
  1569. return;
  1570. ::SendMessage(m_hTTWnd, TTM_SETDELAYTIME, TTDT_AUTOMATIC, timeout);
  1571. }
  1572. void CPopup::SetPos( CPoint& pos )
  1573. {
  1574. m_Pos = pos;
  1575. }
  1576. void CPopup::SetPosInfo( bool bTop, bool bCenterY, bool bLeft, bool bCenterX )
  1577. {
  1578. m_bTop = bTop;
  1579. m_bCenterY = bCenterY;
  1580. m_bLeft = bLeft;
  1581. m_bCenterX = bCenterX;
  1582. }
  1583. void CPopup::AdjustPos( CPoint& pos )
  1584. {
  1585. CRect rel(0,0,0,0);
  1586. CRect rect(0,0,0,0);
  1587. // ::SendMessage(m_hTTWnd, TTM_ADJUSTRECT, TRUE, (LPARAM)&rect);
  1588. ::GetWindowRect(m_hTTWnd,&rect);
  1589. if( ::IsWindow(m_hWndPosRelativeTo) )
  1590. ::GetWindowRect(m_hWndPosRelativeTo, &rel);
  1591. // move the rect to the relative origin
  1592. rect.bottom = rect.Height() + rel.top;
  1593. rect.top = rel.top;
  1594. rect.right = rect.Width() + rel.left;
  1595. rect.left = rel.left;
  1596. // adjust the y position
  1597. rect.OffsetRect( 0, pos.y - (m_bCenterY? rect.Height()/2: (m_bTop? 0: rect.Height())) );
  1598. if( rect.bottom > m_ScreenMaxY )
  1599. rect.OffsetRect( 0, m_ScreenMaxY - rect.bottom );
  1600. // adjust the x position
  1601. rect.OffsetRect( pos.x - (m_bCenterX? rect.Width()/2: (m_bLeft? 0: rect.Width())), 0 );
  1602. if( rect.right > m_ScreenMaxX )
  1603. rect.OffsetRect( m_ScreenMaxX - rect.right, 0 );
  1604. pos.x = rect.left;
  1605. pos.y = rect.top;
  1606. }
  1607. void CPopup::SendToolTipText( CString text )
  1608. {
  1609. m_csToolTipText = text;
  1610. //Replace the tabs with spaces, the tooltip didn't like the \t s
  1611. text.Replace("\t", " ");
  1612. m_TI.lpszText = (LPSTR) (LPCTSTR) text;
  1613. // this allows \n and \r to be interpreted correctly
  1614. ::SendMessage(m_hTTWnd, TTM_SETMAXTIPWIDTH, 0, 500);
  1615. // set the text
  1616. ::SendMessage(m_hTTWnd, TTM_SETTOOLINFO, 0, (LPARAM) (LPTOOLINFO) &m_TI);
  1617. }
  1618. void CPopup::Show( CString text, CPoint pos, bool bAdjustPos )
  1619. {
  1620. if( m_hTTWnd == NULL )
  1621. return;
  1622. m_csToolTipText = text;
  1623. if( !m_bIsShowing )
  1624. ::SendMessage(m_hTTWnd, TTM_TRACKPOSITION, 0, (LPARAM)(DWORD) MAKELONG(-10000,-10000));
  1625. SendToolTipText( text );
  1626. ::SendMessage(m_hTTWnd, TTM_TRACKACTIVATE, true, (LPARAM)(LPTOOLINFO) &m_TI);
  1627. if( bAdjustPos )
  1628. AdjustPos(pos);
  1629. // set the position
  1630. ::SendMessage(m_hTTWnd, TTM_TRACKPOSITION, 0, (LPARAM)(DWORD) MAKELONG(pos.x,pos.y));
  1631. // make sure the tooltip will be on top.
  1632. ::SetWindowPos( m_hTTWnd, m_hWndInsertAfter, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE );
  1633. m_bIsShowing = true;
  1634. }
  1635. void CPopup::Show( CString text )
  1636. {
  1637. m_csToolTipText = text;
  1638. Show( text, m_Pos );
  1639. }
  1640. void CPopup::AllowShow( CString text )
  1641. {
  1642. m_csToolTipText = text;
  1643. if( m_bAllowShow )
  1644. Show( text, m_Pos );
  1645. }
  1646. void CPopup::Hide()
  1647. {
  1648. if( m_hTTWnd == NULL )
  1649. return;
  1650. // deactivate if it is currently activated
  1651. ::SendMessage(m_hTTWnd, TTM_TRACKACTIVATE, FALSE, (LPARAM)(LPTOOLINFO) &m_TI);
  1652. m_bIsShowing = false;
  1653. }