CP_Main.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. // CP_Main.cpp : Defines the class behaviors for the application.
  2. //
  3. #include "stdafx.h"
  4. #include "CP_Main.h"
  5. #include "MainFrm.h"
  6. #include "Misc.h"
  7. #include "SelectDB.h"
  8. #include ".\cp_main.h"
  9. #include "server.h"
  10. #include "Client.h"
  11. #ifdef _DEBUG
  12. #define new DEBUG_NEW
  13. #undef THIS_FILE
  14. static char THIS_FILE[] = __FILE__;
  15. #endif
  16. /////////////////////////////////////////////////////////////////////////////
  17. // The one and only CCP_MainApp object
  18. CCP_MainApp theApp;
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CCP_MainApp
  21. BEGIN_MESSAGE_MAP(CCP_MainApp, CWinApp)
  22. //{{AFX_MSG_MAP(CCP_MainApp)
  23. // NOTE - the ClassWizard will add and remove mapping macros here.
  24. // DO NOT EDIT what you see in these blocks of generated code!
  25. //}}AFX_MSG_MAP
  26. END_MESSAGE_MAP()
  27. /////////////////////////////////////////////////////////////////////////////
  28. // CCP_MainApp construction
  29. CCP_MainApp::CCP_MainApp()
  30. {
  31. m_bAppRunning = false;
  32. m_bAppExiting = false;
  33. m_MainhWnd = NULL;
  34. m_pMainFrame = NULL;
  35. m_bShowingQuickPaste = false;
  36. m_bShowingOptions = false;
  37. m_bShowCopyProperties = false;
  38. m_bRemoveOldEntriesPending = false;
  39. m_IC_bCopy = false;
  40. m_GroupDefaultID = 0;
  41. m_GroupID = 0;
  42. m_GroupParentID = 0;
  43. m_GroupText = "History";
  44. m_FocusID = -1; // -1 == keep previous position, 0 == go to latest ID
  45. m_pDatabase = NULL;
  46. // Place all significant initialization in InitInstance
  47. m_bAsynchronousRefreshView = true;
  48. m_lClipsSent = 0;
  49. m_lClipsRecieved = 0;
  50. m_oldtStartUp = COleDateTime::GetCurrentTime();
  51. m_bExitServerThread = false;
  52. m_lLastGoodIndexForNextworkPassword = -2;
  53. m_HTML_Format = ::RegisterClipboardFormat("HTML Format");
  54. ::InitializeCriticalSection(&m_CriticalSection);
  55. }
  56. CCP_MainApp::~CCP_MainApp()
  57. {
  58. ::DeleteCriticalSection(&m_CriticalSection);
  59. }
  60. /////////////////////////////////////////////////////////////////////////////
  61. // CCP_MainApp initialization
  62. BOOL CCP_MainApp::InitInstance()
  63. {
  64. LOG("InitInstance");
  65. AfxEnableControlContainer();
  66. m_hMutex = CreateMutex(NULL, FALSE, "Ditto Is Now Running");
  67. DWORD dwError = GetLastError();
  68. if(dwError == ERROR_ALREADY_EXISTS)
  69. {
  70. HWND hWnd = (HWND)CGetSetOptions::GetMainHWND();
  71. if(hWnd)
  72. ::SendMessage(hWnd, WM_SHOW_TRAY_ICON, TRUE, TRUE);
  73. return TRUE;
  74. }
  75. AfxOleInit();
  76. AfxInitRichEdit();
  77. CString csFile = CGetSetOptions::GetLanguageFile();
  78. if(!m_Language.LoadLanguageFile(csFile))
  79. {
  80. CString cs;
  81. cs.Format("Error loading language file - %s - \n\n%s", csFile, m_Language.m_csLastError);
  82. MessageBox(m_MainhWnd, cs, "Ditto", MB_OK);
  83. }
  84. m_cfIgnoreClipboard = ::RegisterClipboardFormat("Clipboard Viewer Ignore");
  85. int nRet = CheckDBExists(CGetSetOptions::GetDBPath());
  86. if(nRet == FALSE)
  87. {
  88. AfxMessageBox(theApp.m_Language.GetString("Error_Opening_Database", "Error Opening Database."));
  89. return TRUE;
  90. }
  91. else if(nRet == ERROR_OPENING_DATABASE)
  92. {
  93. CString cs = theApp.m_Language.GetString("Error_Init_Dao", "Unable to initialize DAO/Jet db engine.\nSelect YES to download DAO from http://ditto-cp.sourceforge.net/dao_setup.exe\n\nRestart Ditto after installation of DAO.");
  94. if(MessageBox(NULL, cs, "Ditto", MB_YESNO) == IDYES)
  95. {
  96. ShellExecute(NULL, "open", "http://ditto-cp.sourceforge.net/dao_setup.exe", "", "", SW_SHOW);
  97. }
  98. return TRUE;
  99. }
  100. CMainFrame* pFrame = new CMainFrame;
  101. m_pMainWnd = m_pMainFrame = pFrame;
  102. // prevent no one having focus on startup
  103. TargetActiveWindow();
  104. pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
  105. pFrame->ShowWindow(SW_SHOW);
  106. pFrame->UpdateWindow();
  107. // prevent no one having focus on startup
  108. ReleaseFocus();
  109. return TRUE;
  110. }
  111. void CCP_MainApp::AfterMainCreate()
  112. {
  113. m_MainhWnd = m_pMainFrame->m_hWnd;
  114. ASSERT( ::IsWindow(m_MainhWnd) );
  115. g_Opt.SetMainHWND((long)m_MainhWnd);
  116. g_HotKeys.Init( m_MainhWnd );
  117. // create hotkeys here. They are automatically deleted on exit
  118. m_pDittoHotKey = new CHotKey("DittoHotKey",704); //704 is ctrl-tilda
  119. m_pCopyHotKey = new CHotKey("CopyHotKey");
  120. m_pPosOne = new CHotKey("Position1", 0, true);
  121. m_pPosTwo = new CHotKey("Position2", 0, true);
  122. m_pPosThree = new CHotKey("Position3", 0, true);
  123. m_pPosFour = new CHotKey("Position4", 0, true);
  124. m_pPosFive = new CHotKey("Position5", 0, true);
  125. m_pPosSix = new CHotKey("Position6", 0, true);
  126. m_pPosSeven = new CHotKey("Position7", 0, true);
  127. m_pPosEight = new CHotKey("Position8", 0, true);
  128. m_pPosNine = new CHotKey("Position9", 0, true);
  129. m_pPosTen = new CHotKey("Position10", 0, true);
  130. g_HotKeys.RegisterAll();
  131. // CopyThread initialization
  132. StartCopyThread();
  133. StartStopServerThread();
  134. m_bAppRunning = true;
  135. m_pcpSendRecieveError = NULL;
  136. }
  137. void CCP_MainApp::StartStopServerThread()
  138. {
  139. if(CGetSetOptions::GetDisableRecieve() == FALSE)
  140. {
  141. AfxBeginThread(MTServerThread, m_MainhWnd);
  142. }
  143. else
  144. {
  145. m_bExitServerThread = true;
  146. closesocket(theApp.m_sSocket);
  147. }
  148. }
  149. void CCP_MainApp::StopServerThread()
  150. {
  151. m_bExitServerThread = true;
  152. closesocket(theApp.m_sSocket);
  153. }
  154. void CCP_MainApp::BeforeMainClose()
  155. {
  156. ASSERT( m_bAppRunning && !m_bAppExiting );
  157. m_bAppRunning = false;
  158. m_bAppExiting = true;
  159. g_HotKeys.UnregisterAll();
  160. StopServerThread();
  161. StopCopyThread();
  162. }
  163. /*
  164. Re: Targeting the previous focus window
  165. We usually gain focus after the following messages:
  166. keyboard: WM_KEYUP(0x0101),WM_CHAR(0x0102),WM_HOTKEY(0x0312)
  167. mouse: WM_MOUSEFIRST(0x0200),WM_MOUSEMOVE(0x0200),WM_LBUTTONDOWN(0x0201)
  168. CMainFrame::PreTranslateMessage is used to intercept messages before
  169. they are processed (before we are actually given focus) in order to
  170. save the previous window that had focus.
  171. - It currently just handles "activating" mouse messages when showing.
  172. ShowQPasteWnd also has a call to "TargetActiveWindow" which handles
  173. finding the Target on hotkey activation.
  174. This works well for most window switching (mouse or hotkey), but does
  175. not work well for <Alt>-<Tab> or other window switching applications
  176. (e.g. the taskbar tray), since the previous window was only a means to
  177. switching and not the target itself.
  178. - one solution might be to always monitor the current foreground
  179. window using system hooks or a short (e.g. 1 sec) timer... though this
  180. *might* be cpu intensive (slow). I'm currently looking into using
  181. WH_CBT system hooks in a separate dll (see: robpitt's
  182. http://website.lineone.net/~codebox/focuslog.zip).
  183. */
  184. bool CCP_MainApp::TargetActiveWindow()
  185. {
  186. if(g_Opt.m_bUseHookDllForFocus)
  187. return true;
  188. HWND hOld = m_hTargetWnd;
  189. HWND hNew = ::GetForegroundWindow();
  190. if( hNew == m_hTargetWnd || !::IsWindow(hNew) || IsAppWnd(hNew) )
  191. return false;
  192. m_hTargetWnd = hNew;
  193. if( QPasteWnd() )
  194. QPasteWnd()->UpdateStatus(true);
  195. // Tracking / Debugging
  196. /*
  197. LOG( StrF(
  198. "Target Changed" \
  199. "\n\tOld = 0x%08x: \"%s\"" \
  200. "\n\tNew = 0x%08x: \"%s\"\n",
  201. hOld, (LPCTSTR) GetWndText(hOld),
  202. hNew, (LPCTSTR) GetWndText(hNew) ) );
  203. */
  204. return true;
  205. }
  206. bool CCP_MainApp::ActivateTarget()
  207. {
  208. if( !::IsWindow(m_hTargetWnd) || m_hTargetWnd == ::GetForegroundWindow() )
  209. return false;
  210. ::SetForegroundWindow( m_hTargetWnd );
  211. // ::SetFocus( m_hTargetWnd );
  212. return true;
  213. }
  214. bool CCP_MainApp::ReleaseFocus()
  215. {
  216. if( IsAppWnd(::GetForegroundWindow()) )
  217. return ActivateTarget();
  218. return false;
  219. }
  220. // sends Ctrl-V to the TargetWnd
  221. void CCP_MainApp::SendPaste(bool bActivateTarget)
  222. {
  223. if(bActivateTarget && !ActivateTarget())
  224. {
  225. SetStatus("SendPaste FAILED!",TRUE);
  226. return;
  227. }
  228. keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
  229. keybd_event('V', 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
  230. keybd_event('V', 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  231. keybd_event(VK_CONTROL, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
  232. }
  233. // CopyThread
  234. void CCP_MainApp::StartCopyThread()
  235. {
  236. ASSERT( m_MainhWnd );
  237. CClipTypes* pTypes = LoadTypesFromDB();
  238. // initialize to:
  239. // - m_MainhWnd = send WM_CLIPBOARD_COPIED messages to m_MainhWnd
  240. // - true = use Asynchronous communication (PostMessage)
  241. // - true = enable copying on clipboard changes
  242. // - pTypes = the supported types to use
  243. m_CopyThread.Init( CCopyConfig( m_MainhWnd, true, true, pTypes ) );
  244. VERIFY( m_CopyThread.CreateThread(CREATE_SUSPENDED) );
  245. m_CopyThread.ResumeThread();
  246. }
  247. void CCP_MainApp::StopCopyThread()
  248. {
  249. EnableCbCopy(false);
  250. m_CopyThread.Quit();
  251. SaveCopyClips();
  252. }
  253. // returns the current Clipboard Viewer Connect state (though it might not yet
  254. // be actually connected -- check IsClipboardViewerConnected())
  255. bool CCP_MainApp::ToggleConnectCV()
  256. {
  257. bool bConnect = !GetConnectCV();
  258. SetConnectCV( bConnect );
  259. if( bConnect )
  260. m_pMainFrame->m_TrayIcon.SetIcon( IDR_MAINFRAME );
  261. else
  262. m_pMainFrame->m_TrayIcon.SetIcon( IDI_DITTO_NOCOPYCB );
  263. return bConnect;
  264. }
  265. // Sets a menu entry according to the current Clipboard Viewer Connection status
  266. // - the menu text indicates the available command (opposite the current state)
  267. // - a check mark appears in the rare cases that the menu text actually represents
  268. // the current state, e.g. if we are supposed to be connected, but we somehow
  269. // lose that connection, "Disconnect from Clipboard" will have a check next to it.
  270. void CCP_MainApp::UpdateMenuConnectCV( CMenu* pMenu, UINT nMenuID )
  271. {
  272. if( pMenu == NULL )
  273. return;
  274. bool bConnect = theApp.GetConnectCV();
  275. bool bIsConnected = theApp.IsClipboardViewerConnected();
  276. CString cs;
  277. if( bConnect )
  278. {
  279. cs = theApp.m_Language.GetString("Disconnect_Clipboard", "Disconnect from Clipboard.");
  280. pMenu->ModifyMenu(nMenuID, MF_BYCOMMAND, nMenuID, cs);
  281. // add a check mark if we are still disconnected (temporarily)
  282. if( !bIsConnected )
  283. pMenu->CheckMenuItem(nMenuID, MF_CHECKED);
  284. else
  285. pMenu->CheckMenuItem(nMenuID, MF_UNCHECKED);
  286. }
  287. else // CV is disconnected, so provide the option of connecting
  288. {
  289. cs = theApp.m_Language.GetString("Connect_Clipboard", "Connect to Clipboard.");
  290. pMenu->ModifyMenu(nMenuID, MF_BYCOMMAND, nMenuID, cs);
  291. // add a check mark if we are still connected (temporarily)
  292. if( bIsConnected )
  293. pMenu->CheckMenuItem(nMenuID, MF_CHECKED);
  294. else
  295. pMenu->CheckMenuItem(nMenuID, MF_UNCHECKED);
  296. }
  297. }
  298. // Allocates a new CClipTypes
  299. CClipTypes* CCP_MainApp::LoadTypesFromDB()
  300. {
  301. CClipTypes* pTypes = new CClipTypes;
  302. try
  303. {
  304. CTypesTable recset;
  305. recset.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Types" ,NULL);
  306. while(!recset.IsEOF())
  307. {
  308. pTypes->Add( GetFormatID(recset.m_TypeText) );
  309. recset.MoveNext();
  310. }
  311. recset.Close();
  312. }
  313. catch(CDaoException* e)
  314. {
  315. ASSERT(FALSE);
  316. e->Delete();
  317. }
  318. if( pTypes->GetSize() <= 0 )
  319. {
  320. pTypes->Add(CF_TEXT);
  321. pTypes->Add(RegisterClipboardFormat(CF_RTF));
  322. pTypes->Add(CF_DIB);
  323. }
  324. return pTypes;
  325. }
  326. void CCP_MainApp::ReloadTypes()
  327. {
  328. CClipTypes* pTypes = LoadTypesFromDB();
  329. if( pTypes )
  330. m_CopyThread.SetSupportedTypes( pTypes );
  331. }
  332. long CCP_MainApp::SaveCopyClips()
  333. {
  334. long lID = 0;
  335. int count;
  336. CClipList* pClips = m_CopyThread.GetClips(); // we now own pClips
  337. if( !pClips )
  338. return 0;
  339. CClipList* pCopyOfClips = NULL;
  340. if(g_Opt.m_lAutoSendClientCount > 0)
  341. {
  342. //The thread will free these
  343. pCopyOfClips = new CClipList;
  344. if(pCopyOfClips != NULL)
  345. {
  346. *pCopyOfClips = *pClips;
  347. }
  348. }
  349. bool bEnteredThread = false;
  350. count = pClips->AddToDB( true );
  351. if( count > 0 )
  352. {
  353. lID = pClips->GetTail()->m_ID;
  354. OnCopyCompleted(lID, count);
  355. if(g_Opt.m_lAutoSendClientCount > 0)
  356. {
  357. AfxBeginThread(SendClientThread, pCopyOfClips);
  358. bEnteredThread = true;
  359. }
  360. }
  361. if(bEnteredThread == false)
  362. delete pCopyOfClips;
  363. delete pClips;
  364. return lID;
  365. }
  366. void CCP_MainApp::RefreshView()
  367. {
  368. if( m_bShowingQuickPaste )
  369. {
  370. ASSERT( QPasteWnd() );
  371. if(m_bAsynchronousRefreshView)
  372. QPasteWnd()->PostMessage(WM_REFRESH_VIEW);
  373. else
  374. QPasteWnd()->SendMessage(WM_REFRESH_VIEW);
  375. }
  376. }
  377. void CCP_MainApp::OnPasteCompleted()
  378. {
  379. // the list only changes if UpdateTimeOnPaste is true (updated time)
  380. if( g_Opt.m_bUpdateTimeOnPaste )
  381. RefreshView();
  382. }
  383. void CCP_MainApp::OnCopyCompleted(long lLastID, int count)
  384. {
  385. if( count <= 0 )
  386. return;
  387. // queue a message to RemoveOldEntries
  388. Delayed_RemoveOldEntries( 60000 );
  389. // update copy statistics
  390. CGetSetOptions::SetTripCopyCount( -count );
  391. CGetSetOptions::SetTotalCopyCount( -count );
  392. // if we are in the History group, focus on the latest copy
  393. if( m_GroupID == 0 )
  394. m_FocusID = 0;
  395. RefreshView();
  396. ShowCopyProperties( lLastID );
  397. }
  398. // Internal Clipboard for cut/copy/paste items between Groups
  399. // if NULL, this uses the current QPaste selection
  400. void CCP_MainApp::IC_Cut( ARRAY* pIDs )
  401. {
  402. if( pIDs == NULL )
  403. {
  404. if( QPasteWnd() )
  405. QPasteWnd()->m_lstHeader.GetSelectionItemData( m_IC_IDs );
  406. else
  407. m_IC_IDs.SetSize(0);
  408. }
  409. else
  410. m_IC_IDs.Copy( *pIDs );
  411. m_IC_bCopy = false;
  412. if( QPasteWnd() )
  413. QPasteWnd()->UpdateStatus();
  414. }
  415. // if NULL, this uses the current QPaste selection
  416. void CCP_MainApp::IC_Copy( ARRAY* pIDs )
  417. {
  418. if( pIDs == NULL )
  419. {
  420. if( QPasteWnd() )
  421. QPasteWnd()->m_lstHeader.GetSelectionItemData( m_IC_IDs );
  422. else
  423. m_IC_IDs.SetSize(0);
  424. }
  425. else
  426. m_IC_IDs.Copy( *pIDs );
  427. m_IC_bCopy = true;
  428. if( QPasteWnd() )
  429. QPasteWnd()->UpdateStatus();
  430. }
  431. void CCP_MainApp::IC_Paste()
  432. {
  433. if( m_IC_IDs.GetSize() <= 0 )
  434. return;
  435. if( m_IC_bCopy )
  436. m_IC_IDs.CopyTo( GetValidGroupID() );
  437. else // Move
  438. m_IC_IDs.MoveTo( GetValidGroupID() );
  439. // don't process the same items twice.
  440. m_IC_IDs.SetSize(0);
  441. RefreshView();
  442. }
  443. // Groups
  444. BOOL CCP_MainApp::EnterGroupID( long lID )
  445. {
  446. BOOL bResult = FALSE;
  447. if( m_GroupID == lID )
  448. return TRUE;
  449. // if we are switching to the parent, focus on the previous group
  450. if( m_GroupParentID == lID && m_GroupID > 0 )
  451. m_FocusID = m_GroupID;
  452. switch( lID )
  453. {
  454. case 0: // History Group "ID"
  455. m_FocusID = -2;
  456. m_GroupID = 0;
  457. m_GroupParentID = 0;
  458. m_GroupText = "History";
  459. bResult = TRUE;
  460. break;
  461. case -1: // All Groups "ID"
  462. m_GroupID = -1;
  463. m_GroupParentID = 0;
  464. m_GroupText = "Groups";
  465. bResult = TRUE;
  466. break;
  467. default: // Normal Group
  468. try
  469. {
  470. CMainTable recs;
  471. COleVariant varKey( lID, VT_I4 );
  472. recs.Open( dbOpenTable, "Main" );
  473. recs.SetCurrentIndex("lID");
  474. // Find first record whose [lID] field == lID
  475. if( recs.Seek(_T("="), &varKey) && recs.m_bIsGroup )
  476. {
  477. m_GroupID = recs.m_lID;
  478. m_GroupParentID = recs.m_lParentID;
  479. // if( m_GroupParentID == 0 )
  480. // m_GroupParentID = -1; // back out into "all top-level groups" list.
  481. m_GroupText = recs.m_strText;
  482. bResult = TRUE;
  483. }
  484. recs.Close();
  485. }
  486. CATCHDAO
  487. break;
  488. }
  489. if( bResult )
  490. {
  491. theApp.RefreshView();
  492. if( QPasteWnd() )
  493. QPasteWnd()->UpdateStatus( true );
  494. }
  495. return bResult;
  496. }
  497. // returns a usable group id (not negative)
  498. long CCP_MainApp::GetValidGroupID()
  499. {
  500. if( m_GroupID <= 0 )
  501. return 0;
  502. return m_GroupID;
  503. }
  504. // sets a valid id
  505. void CCP_MainApp::SetGroupDefaultID( long lID )
  506. {
  507. if( m_GroupDefaultID == lID )
  508. return;
  509. if( lID <= 0 )
  510. m_GroupDefaultID = 0;
  511. else
  512. m_GroupDefaultID = lID;
  513. if( QPasteWnd() )
  514. QPasteWnd()->UpdateStatus();
  515. }
  516. // Window States
  517. void CCP_MainApp::SetStatus( const char* status, bool bRepaintImmediately )
  518. {
  519. m_Status = status;
  520. if( QPasteWnd() )
  521. QPasteWnd()->UpdateStatus( bRepaintImmediately );
  522. }
  523. void CCP_MainApp::ShowPersistent( bool bVal )
  524. {
  525. g_Opt.SetShowPersistent( bVal );
  526. // give some visual indication
  527. if( m_bShowingQuickPaste )
  528. {
  529. ASSERT( QPasteWnd() );
  530. QPasteWnd()->SetCaptionColorActive(!g_Opt.m_bShowPersistent, theApp.GetConnectCV());
  531. QPasteWnd()->RefreshNc();
  532. }
  533. }
  534. void CCP_MainApp::ShowCopyProperties( long lID )
  535. {
  536. if( m_bShowCopyProperties && lID > 0 )
  537. {
  538. HWND hWndFocus = ::GetForegroundWindow();
  539. m_bShowCopyProperties = false;
  540. ::SendMessage(m_MainhWnd, WM_COPYPROPERTIES, lID, 0); // modal
  541. ::SetForegroundWindow(hWndFocus);
  542. }
  543. }
  544. void CCP_MainApp::Delayed_RemoveOldEntries( UINT delay )
  545. {
  546. if( !m_bRemoveOldEntriesPending )
  547. {
  548. m_bRemoveOldEntriesPending = true;
  549. ((CMainFrame*)theApp.m_pMainWnd)->SetTimer( REMOVE_OLD_ENTRIES_TIMER, delay, 0 );
  550. }
  551. }
  552. /////////////////////////////////////////////////////////////////////////////
  553. // CCP_MainApp message handlers
  554. int CCP_MainApp::ExitInstance()
  555. {
  556. LOG("ExitInstance");
  557. CloseDB();
  558. return CWinApp::ExitInstance();
  559. }
  560. CDaoDatabase* CCP_MainApp::EnsureOpenDB(CString csName)
  561. {
  562. try
  563. {
  564. if(!m_pDatabase)
  565. m_pDatabase = new CDaoDatabase;
  566. if(!m_pDatabase->IsOpen())
  567. {
  568. if(csName == "")
  569. m_pDatabase->Open(GetDBName());
  570. else
  571. m_pDatabase->Open(csName);
  572. }
  573. if(m_pMainWnd)
  574. ((CMainFrame *)m_pMainWnd)->ResetKillDBTimer();
  575. }
  576. CATCHDAO
  577. return m_pDatabase;
  578. }
  579. BOOL CCP_MainApp::CloseDB()
  580. {
  581. if(m_pDatabase)
  582. {
  583. if(m_pDatabase->IsOpen())
  584. m_pDatabase->Close();
  585. delete m_pDatabase;
  586. m_pDatabase = NULL;
  587. }
  588. return TRUE;
  589. }
  590. // return TRUE if there is more idle processing to do
  591. BOOL CCP_MainApp::OnIdle(LONG lCount)
  592. {
  593. // let winapp handle its idle processing
  594. if( CWinApp::OnIdle(lCount) )
  595. return TRUE;
  596. return FALSE;
  597. }
  598. CString CCP_MainApp::GetTargetName()
  599. {
  600. char cWindowText[100];
  601. HWND hParent = m_hTargetWnd;
  602. ::GetWindowText(hParent, cWindowText, 100);
  603. while(strlen(cWindowText) <= 0)
  604. {
  605. hParent = ::GetParent(hParent);
  606. if(hParent == NULL)
  607. break;
  608. ::GetWindowText(hParent, cWindowText, 100);
  609. }
  610. return cWindowText;
  611. }
  612. void CCP_MainApp::SetConnectCV(bool bConnect)
  613. {
  614. m_CopyThread.SetConnectCV(bConnect);
  615. if(QPasteWnd())
  616. {
  617. QPasteWnd()->SetCaptionColorActive(!g_Opt.m_bShowPersistent, theApp.GetConnectCV());
  618. QPasteWnd()->RefreshNc();
  619. }
  620. }