OSDN Git Service

8aece02f90ed0b4f3c3faa217109010224105d72
[dokopop/dokopop.git] / DCHookTest / DCHookMain.cpp
1 //---------------------------------------------------------------------------
2 #include <vcl.h>
3 #pragma hdrstop
4 #include <tchar.h>
5 #include "DCHookMain.h"
6 #include <stdio.h>
7 #include <shellapi.h>
8 #include "StringLib.h"
9 #include "PopupConfig.h"
10 #include "Notify.h"
11 #include "DCHookLoader.h"
12 #include "prgprof.h"
13 #include "MODINotifyDlg.h"
14 #include "prgconfig.h"
15 #include "OCRTextFrm.h"
16 #include "MonitorScale.h"
17 //---------------------------------------------------------------------------
18 #pragma package(smart_init)
19
20 /*------------------------------------------*/
21 /*              Configuration                                           */
22 /*------------------------------------------*/
23 // Popup\82Ì\82½\82Ñ\82ÉDLL\82ðUnload/Load\82·\82é
24 // \94½\89\9e\82µ\82È\82­\82È\82Á\82½\82Æ\82«\82Ì\82½\82ß\82Ì\91Î\8fÇ\97Ã\96@
25 // Note: 2013.3.12
26 //      inc.srch ON\82Ì\82Æ\82«\81AMoveSent\82ª\8fí\82Éreset\82³\82ê\82Ä\82µ\82Ü\82¤\82½\82ß\81A
27 //      mouse\82ªstill\8fó\91Ô\82Å\82 \82Á\82Ä\82à\89½\93x\82àinc.srch\82Ì\83\8a\83N\83G\83X\83g\82ª\82â\82Á\82Ä\82­\82é\81B
28 //      \82Ù\82©\81Apopup/inc.srch\82ð\82â\82é\82½\82Ñ\82ÉDLL\93à\82Ì\95Ï\90\94\82ªreset\82³\82ê\82é\82½\82ß\82±\82ê\82Í\82æ\82ë\82µ\82­\82È\82¢\81B
29 #define DETACHRELEASE           0
30
31 #define MIGROUP_INDEX           1               // \8e«\8f\91\83O\83\8b\81[\83v\95Ï\8dX\83\81\83j\83\85\81[\82Ìindex
32
33 // PDIC\8bN\93®\8cã\82ÌOpenLink()\8e¸\94s\8e\9e\82Ìretry\82¨\82æ\82Ñwaittime
34 #define OPEN_RETRY                      5
35 #define OPEN_WAITTIME           500             // [mSec]
36
37 #define DPI_DETECT                      0               // DPI Detect in main (monitor\82²\82Æ\82Ì\90Ý\92è\82ª\82Å\82«\82È\82¢\82½\82ßdebug\97p)
38
39 #define DEF_USE64                       (fWow64)
40
41 /*------------------------------------------*/
42 /*              Definitions                                                     */
43 /*------------------------------------------*/
44 #define URL_MODI_INSTALL        "http://support.microsoft.com/kb/982760"
45
46 #define DEF_POPUPKEY            (KF_CONTROL)
47 #define DEF_TOGGLEKEY           (KF_CONTROL+KF_MENU)
48
49 #define WM_AMODI                        (WM_APP+0x400)  // app communication message with AMODI
50
51 #define FLG_MOVESEND            0x40000000      // mouse move send
52
53 #pragma resource "*.dfm"
54 TDCHookMainForm *DCHookMainForm;
55
56 #define COMPANYNAME     "Software\\DokoPopProject\\"
57
58 bool Reboot = false;
59
60 /*------------------------------------------*/
61 /*              Prototypes                                                      */
62 /*------------------------------------------*/
63 bool DdePoke( TDdeClientConv *dde, AnsiString Item, AnsiString Data );
64 #ifdef USE_UNICODE
65 // Unicode\82Å\93n\82·\8fê\8d\87
66 bool DdePoke( TDdeClientConv *dde, AnsiString Item, const wchar_t *Data );
67 bool DdeRequest( TDdeClientConv *dde, AnsiString Item, char *Data, int &inoutDataLen );
68 #endif;
69 void GetGroupList(TMyIni &ini, TStringList &list);
70
71 //---------------------------------------------------------------------------
72 __fastcall TDCHookMainForm::TDCHookMainForm(TComponent* Owner)
73         : TForm(Owner)
74 {
75         hDll = NULL;
76         EnablePopup = true;
77
78 #if 0
79         WindowsNT = false;
80
81         OSVERSIONINFO VersionInfo;
82         VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
83         GetVersionEx(&VersionInfo);
84         switch (VersionInfo.dwPlatformId){
85                 case VER_PLATFORM_WIN32_NT:
86                         WindowsNT = true;
87                         break;
88         }
89 #endif
90         CheckWOW64();
91         BootUp = true;
92         Capturing = false;
93         PopupText = NULL;
94         DoPopupRetry = 0;
95         CaptureMode = CM_TEXT | CM_IMAGE;
96         AMODIAvail = false;
97         MouseIncSrch = false;
98 }
99 //---------------------------------------------------------------------------
100 void __fastcall TDCHookMainForm::FormCreate(TObject *Sender)
101 {
102         Ini = new TMyIni( HKEY_CURRENT_USER, COMPANYNAME APPREGNAME, true );
103 //      DBW("Handle=%08X",Handle);
104
105 #ifdef _DEBUG
106         Left = Ini->ReadInteger( PFS_MAIN, "Left", Left );
107         Top = Ini->ReadInteger( PFS_MAIN, "Top", Top );
108         Width = Ini->ReadInteger( PFS_MAIN, "Width", Width );
109         Height = Ini->ReadInteger( PFS_MAIN, "Height", Height );
110 #endif
111
112         GroupOpen = Ini->ReadInteger( PFS_CONFIG, PFS_GROUPOPEN, false );
113         GroupName = Ini->ReadString( PFS_CONFIG, PFS_GROUPNAME, "" );
114         CtrlClose = Ini->ReadInteger( PFS_CONFIG, PFS_CTRLCLOSE, false );
115         IgnoreJ   = Ini->ReadInteger( PFS_CONFIG, PFS_IGNOREJ, true );
116         Banner    = Ini->ReadInteger( PFS_CONFIG, PFS_BANNER, true );
117
118 #ifndef _DEBUG
119         BorderStyle = bsNone;
120
121         Memo->Visible = false;
122         Panel1->Visible = false;
123         Splitter1->Visible = false;
124         Menu->Items->Delete( 0 );
125         Image->Visible = true;
126 //      Title->Caption = Title->Caption + "   " + StrVersion;
127 //      Title->Align = alBottom;
128 #if 0
129         Title->Visible = true;
130 #endif
131
132         AnsiString bmp = ExtractFilePath( Application->ExeName );
133         bmp += NAME_BMPFILE;
134         if ( FileExists( bmp ) ){
135                 Image->Picture->Bitmap->LoadFromFile( bmp );
136         }
137
138         Width = Image->Picture->Width;
139         Height = Image->Picture->Height;
140
141         // To center
142         Left += ( ( ( GetSystemMetrics( SM_CXSCREEN ) - ( Width ) ) / 2 + 4 ) & ~7 ) - Left;
143         Top += ( ( GetSystemMetrics( SM_CYSCREEN ) - ( Height ) ) / 2 ) - Top;
144 #endif
145
146         SavedWidth = Width;
147
148 #ifdef _DEBUG
149         BootTimer->Interval = 100;
150         Width = SavedWidth;
151         WindowState = wsNormal;
152 #else
153         if ( !Banner ){
154                 BootTimer->Interval = 10;
155                 // \82È\82ñ\82ÆVisible = false;\82É\82·\82é\82Æ\81A
156                 // \83A\83C\83R\83\93\89»\82µ\82½\82Æ\82«\81E\81E\81E\83A\83C\83R\83\93\82ª\95\\8e¦\82³\82ê\82é
157                 // \83A\83C\83R\83\93\89»\82µ\82È\82¢\82Æ\82«\81E\81E\83A\83C\83R\83\93\82Í\8fo\82Ä\82±\82È\82¢
158                 // \95Ï\82È\8ed\97l\81H
159                 // \82Æ\82¢\82¤\82í\82¯\82Å\95\9d\82ð\83[\83\8d\82É\82µ\82ÄWindow\82ð\94ñ\95\\8e¦\89»\82Æ\82¤\82¢\8e×\93¹\82È\95û\96@
160                 // \8dÅ\8f\89\82©\82ç\82¸\82Á\82ÆVisible=false\82Æ\82¢\82¤\95û\96@\82à\82 \82é\82ª\81A
161                 // VCL\82ªMainWindow\82ð\95K\82¸visible\82É\82·\82é\8f\88\97\9d\82ð\8ds\82Á\82Ä\82¢\82é\82½\82ß\95s\89Â\94\
162                 // \82Ù\82©\82É\82¢\82¢\95û\96@\82ª\82 \82Á\82½\82æ\82¤\82È\8bC\82ª\82·\82é\82ª\81A\81A\81A\81
163                 Width = 0;
164         } else {
165                 Visible = true; // \8dÅ\8f¬\89»\82Å\8bN\93®\82·\82é\82Æ\81A\83A\83C\83R\83\93\95\\8e¦\82ª\8fÁ\82¦\82È\82¢\82½\82ß\81B
166                                                 // \82±\82Ì\95û\96@\82ª\93K\93\96\82Å\82 \82é\82©\82Ç\82¤\82©\90[\82­\8dl\82¦\82Ä\82¢\82È\82¢\81E\81E
167                                                 // (\82½\82Ü\82½\82Ü\82¤\82Ü\82­\93®\82¢\82½:-)
168                 Width = SavedWidth;
169                 WindowState = wsNormal;
170         }
171 #endif
172
173         //TODO: default=ON\82É\82·\82é\82Æ\95s\88À\92è\82É\82È\82é\82Ì\82Å\82µ\82Î\82ç\82­def=false
174         //MouseIncSrch = Ini->ReadInteger( PFS_CONFIG, PFS_INCSRCH, MouseIncSrch );
175         CaptureMode = Ini->ReadInteger( PFS_CONFIG, PFS_CAPTURE_MODE, CaptureMode );
176         InitAMODI();
177         btnOK->Left = (SavedWidth - btnOK->Width)>>1;
178         btnOK->Top = Height - btnOK->Height - 8;
179         lbVersion->Caption = StrVersion;
180         lbVersion->Left = btnOK->Left + btnOK->Width + 4;
181         lbVersion->Top = btnOK->Top;
182         
183         BootTimer->Enabled = true;
184
185         if (!AMODIAvail && (CaptureMode & CM_IMAGE)){
186                 tmMODINotify->Enabled = true;
187         }
188
189 //      Application->OnIdle = IdleHandler;
190 }
191 //---------------------------------------------------------------------------
192 void __fastcall TDCHookMainForm::FormCloseQuery(TObject *Sender,
193           bool &CanClose)
194 {
195         if (AMODIAvail){
196                 TerminateAMODI();
197         }
198         if (OCRTextForm){
199                 OCRTextForm->Visible = false;
200                 delete OCRTextForm;
201                 OCRTextForm = NULL;
202         }
203         RegisterTrayIcon( false );
204 #ifdef _DEBUG
205         WINDOWPLACEMENT wp;
206         wp.length = sizeof(WINDOWPLACEMENT);
207         GetWindowPlacement( Handle, &wp );
208         RECT &rc = wp.rcNormalPosition;
209         Ini->WriteInteger( PFS_MAIN, "Left", rc.left );
210         Ini->WriteInteger( PFS_MAIN, "Top", rc.top );
211         Ini->WriteInteger( PFS_MAIN, "Width", rc.right - rc.left );
212         Ini->WriteInteger( PFS_MAIN, "Height", rc.bottom - rc.top );
213 #endif
214
215         miUnhookClick( this );
216
217         delete Ini;
218         if (PopupText){
219                 delete[] PopupText;
220                 PopupText = NULL;
221         }
222 }
223 //---------------------------------------------------------------------------
224 void __fastcall TDCHookMainForm::FormKeyPress(TObject *Sender, char &Key)
225 {
226 #ifndef _DEBUG
227         if ( Key == 0x1b ){
228                 Key = 0;
229                 Start();
230         }
231 #endif
232 }
233 #if 0
234 void __fastcall TDCHookMainForm::IdleHandler(TObject *sender, bool &done)
235 {
236         if (NotifyAMODIEnabled){
237                 NotifyAMODIEnabled = false;
238                 NotifyAMODI();
239         }
240 }
241 #endif
242 //---------------------------------------------------------------------------
243 // Menu event
244 //---------------------------------------------------------------------------
245 void __fastcall TDCHookMainForm::miDicGroup(TObject *Sender)
246 {
247         // \8e«\8f\91\83O\83\8b\81[\83v
248         AnsiString name = ((TMenuItem*)Sender)->Caption;
249         if ( name.Length() ){
250                 OpenDicGroup( name.c_str() );
251         }
252 }
253 //---------------------------------------------------------------------------
254 void __fastcall TDCHookMainForm::miClickOnlyClick(TObject *Sender)
255 {
256         miClickOnly->Checked = !miClickOnly->Checked;
257         EnableClickOnly( miClickOnly->Checked );
258         MenuClosed();
259 }
260 //---------------------------------------------------------------------------
261 void __fastcall TDCHookMainForm::miIncSearchClick(TObject *Sender)
262 {
263         miIncSearch->Checked = !miIncSearch->Checked;
264         MouseIncSrch = miIncSearch->Checked;
265         Ini->WriteInteger( PFS_CONFIG, PFS_INCSRCH, MouseIncSrch );
266         SetupConfig2();
267         if (MouseIncSrch){
268                 HWND hwnd = FindPdic();
269                 if (hwnd){
270                         MoveToTop(hwnd);
271                 }
272         }
273 }
274 //---------------------------------------------------------------------------
275 #if 0   // change capture mode
276         if (!AMODIAvail && (CaptureMode & CM_IMAGE)){
277                 InitAMODI();
278         }
279         if (AMODIAvail){
280                 SetupConfig2();
281         } else {
282                 NotifyAMODI();
283         }
284
285         MenuClosed();
286 #endif
287 //---------------------------------------------------------------------------
288 void __fastcall TDCHookMainForm::miEnablePopupClick(TObject *Sender)
289 {
290         if ( miEnablePopup->Checked ){
291                 miUnhookClick( this );
292                 EnablePopup = false;
293         } else {
294                 miHookClick( this );
295                 EnablePopup = true;
296         }
297         MenuClosed();
298 }
299 //---------------------------------------------------------------------------
300 void __fastcall TDCHookMainForm::miOCRTextClick(TObject *Sender)
301 {
302         if (!OCRTextForm) OCRTextForm = new TOCRTextForm(this);
303         OCRTextForm->Visible = true;
304 }
305 //---------------------------------------------------------------------------
306 void __fastcall TDCHookMainForm::miOptionClick(TObject *Sender)
307 {
308         if (PopupConfigDlg){
309                 MoveToTop(PopupConfigDlg->Handle);
310                 return;
311         }
312
313         // Configuration //
314         PopupConfigDlg = new TPopupConfigDlg( this );
315         PopupConfigDlg->cbGroupOpen->Checked = GroupOpen;
316         PopupConfigDlg->edGroupName->Text = GroupName;
317         PopupConfigDlg->SetPopupKey( Ini->ReadInteger( PFS_CONFIG, PFS_POPUPKEY, DEF_POPUPKEY ) );
318         PopupConfigDlg->SetToggleKey( Ini->ReadInteger( PFS_CONFIG, PFS_TOGGLEKEY, DEF_TOGGLEKEY ) );
319         PopupConfigDlg->cbCtrlClose->Checked = CtrlClose;
320         PopupConfigDlg->cbIgnoreJ->Checked = IgnoreJ;
321         PopupConfigDlg->cbBanner->Checked = Banner;
322         bool useAMODI = CaptureMode & CM_IMAGE ? true : false;
323         PopupConfigDlg->SetCaptureMode( CaptureMode );
324         PopupConfigDlg->SetScaler( Ini->ReadInteger(PFS_CONFIG, PFS_SCALE, 0) );
325         PopupConfigDlg->edAMODIPath->Text = AMODIPath;
326         PopupConfigDlg->SetMODIAvail( AMODIAvail );
327         bool use64 = Ini->ReadInteger(PFS_CONFIG, PFS_USE64, DEF_USE64);
328         PopupConfigDlg->cbUse64->Checked = use64;
329         SetForegroundWindow( PopupConfigDlg->Handle );
330         if ( PopupConfigDlg->ShowModal() == IDOK ){
331                 GroupOpen = PopupConfigDlg->cbGroupOpen->Checked;
332                 GroupName = PopupConfigDlg->edGroupName->Text;
333                 CtrlClose = PopupConfigDlg->cbCtrlClose->Checked;
334                 IgnoreJ = PopupConfigDlg->cbIgnoreJ->Checked;
335                 Banner = PopupConfigDlg->cbBanner->Checked;
336                 AMODIPath = PopupConfigDlg->edAMODIPath->Text;
337                 Ini->WriteInteger( PFS_CONFIG, PFS_POPUPKEY,
338                         PopupConfigDlg->GetPopupKey() );
339                 Ini->WriteInteger( PFS_CONFIG, PFS_TOGGLEKEY,
340                         PopupConfigDlg->GetToggleKey() );
341                 CaptureMode = PopupConfigDlg->GetCaptureMode();
342                 Ini->WriteInteger( PFS_CONFIG, PFS_CAPTURE_MODE, CaptureMode );
343                 Ini->WriteInteger( PFS_CONFIG, PFS_SCALE, PopupConfigDlg->GetScaler() );
344                 Ini->WriteString(PFS_CONFIG, PFS_AMODIPATH, AMODIPath.c_str());
345                 Ini->WriteInteger(PFS_CONFIG, PFS_USE64, PopupConfigDlg->cbUse64->Checked);
346                 SaveConfig();
347                 SetupConfig();
348                 tmReInit->Enabled = false;
349                 if (!useAMODI && (CaptureMode & CM_IMAGE) && !AMODIAvail){
350                         // AMODI off->ON \82©\82 AMODI\82ª\82¢\82È\82¢\8fê\8d\87
351                         NotifyAMODI();
352                 }
353                 if (PopupConfigDlg->cbUse64->Checked != use64){
354                         // 64bit hook \95Ï\8dX\8e\9e
355                         Unhook();
356                         Hook();
357                 }
358         }
359         delete PopupConfigDlg;
360         PopupConfigDlg = NULL;
361 }
362 void __fastcall TDCHookMainForm::miReadMeClick(TObject *Sender)
363 {
364         ShowManual(Handle);
365 }
366 //---------------------------------------------------------------------------
367 void __fastcall TDCHookMainForm::miAboutClick(TObject *Sender)
368 {
369         // show version dialog
370 #if 1
371         Width = SavedWidth;
372         btnOK->Visible = true;
373         btnOK->SetFocus();
374         Visible = true;
375 #else
376         VersionDlg = new TVersionDlg( this );
377         VersionDlg->ShowModal();
378         delete VersionDlg;
379 #endif
380 }
381 //---------------------------------------------------------------------------
382 void __fastcall TDCHookMainForm::miCheckLatestClick(TObject *Sender)
383 {
384         ShowLatestVersion();
385 }
386 //---------------------------------------------------------------------------
387 void __fastcall TDCHookMainForm::miCloseClick(TObject *Sender)
388 {
389         MenuClosed();
390 }
391 //---------------------------------------------------------------------------
392 void __fastcall TDCHookMainForm::miReloadClick(TObject *Sender)
393 {
394         // \8dÄ\8bN\93®
395         Unhook();
396         Hook();
397         MenuClosed();
398 }
399 //---------------------------------------------------------------------------
400 void __fastcall TDCHookMainForm::miHookClick(TObject *Sender)
401 {
402         if ( !Hook() ){
403                 Application->MessageBox( "DLL\82ð\8f\89\8aú\89»\82·\82é\82±\82Æ\82ª\82Å\82«\82Ü\82¹\82ñ\r\8fI\97¹\82µ\82Ü\82·", APPNAME, MB_OK );
404                 Close();
405         }
406 }
407 //---------------------------------------------------------------------------
408 void __fastcall TDCHookMainForm::miUnhookClick(TObject *Sender)
409 {
410         Unhook();
411 }
412 //---------------------------------------------------------------------------
413 void __fastcall TDCHookMainForm::miConfigClick(TObject *Sender)
414 {
415         miOptionClick(Sender);
416 }
417 //---------------------------------------------------------------------------
418 void __fastcall TDCHookMainForm::miDdeTestClick(TObject *Sender)
419 {
420 #ifdef _DEBUG
421         DoPopup( _t("test"), 0, NULL, false );
422 #endif
423 }
424 //---------------------------------------------------------------------------
425 void __fastcall TDCHookMainForm::miTestClick(TObject *Sender)
426 {
427 #ifdef _DEBUG
428 #if 1
429         hDll->Init32(Handle);
430 #endif
431 #if 0
432         NotifyAMODI();
433 #endif
434 #if 0
435         miIncSearchClick(Sender);
436 #endif
437 #if 0
438         if (hDll){
439                 hDll->Capture();
440         }
441 #endif
442 #endif  // _DEBUG
443 }
444 //---------------------------------------------------------------------------
445 void __fastcall TDCHookMainForm::miExitClick(TObject *Sender)
446 {
447         Close();
448 }
449 //---------------------------------------------------------------------------
450 // Popup on tray icon //
451 void __fastcall TDCHookMainForm::pmTrayIconPopup(TObject *Sender)
452 {
453         // Add group names to menu
454         TAppIni ini;
455         if ( !ini.hroot ){
456                 return;
457         }
458
459         int sel = ini.ReadInteger( PFS_COMMON, PFS_GRPSEL, -1 );
460
461         TStringList *strs = new TStringList;
462         TMenuItem *sub = pmTrayIcon->Items->Items[MIGROUP_INDEX];
463         for ( ;sub->Count;){
464                 sub->Delete(0);
465         }
466         GetGroupList(ini, *strs);
467         int index = 0;
468         for ( int i=0;i<strs->Count;i++ ){
469                 AnsiString name = strs->Strings[i];
470                 if (name.IsEmpty() || name.AnsiPos("::")==1){
471                         continue;       // Ignore the group.
472                 }
473                 TMenuItem *item = new TMenuItem( this );
474                 item->Caption = name;
475                 item->OnClick = miDicGroup;
476                 sub->Add( item );
477                 // Check current group name //
478                 if ( sel == index ){
479                         item->Checked = true;
480                 }
481                 index++;
482         }
483         delete strs;
484         miGroup->Visible = sub->Count != 0;
485         // Check enable popup item //
486         miIncSearch->Checked = MouseIncSrch;
487         miEnablePopup->Checked = EnablePopup;
488
489         miOCRText->Visible = CaptureMode & CM_IMAGE ? true : false;
490 }
491 //---------------------------------------------------------------------------
492 void __fastcall TDCHookMainForm::btnOKClick(TObject *Sender)
493 {
494 #ifndef _DEBUG
495         Width = 0;
496 #endif
497         MenuClosed();
498 }
499 //---------------------------------------------------------------------------
500 // Timers
501 //---------------------------------------------------------------------------
502 void __fastcall TDCHookMainForm::TestTimerTimer(TObject *Sender)
503 {
504 #ifdef _DEBUG
505 #if 0
506         if ( DCDebug ){
507                 char *p = (char*)DCDebug( );
508                 if ( memcmp( share, p, COMPSIZE ) ){
509                         DBW("Different");
510                         for ( int i=0;i<COMPSIZE;i++ ){
511                                 DBW("[%02X:%02X]", (unsigned char)share[i],(unsigned char)p[i]);
512                         }
513                         memcpy( share, p, COMPSIZE );
514                 }
515         }
516 #endif
517 #endif
518 }
519 //---------------------------------------------------------------------------
520 void __fastcall TDCHookMainForm::BootTimerTimer(TObject *Sender)
521 {
522         Start();
523 }
524 //---------------------------------------------------------------------------
525 // \82±\82ê\82ð\82â\82ç\82È\82¢\82Æ\81A\81h\83\81\83j\83\85\81[\82ð\95Â\82\82é\81h\82ð\8eÀ\8ds\8cã\81A
526 // \83A\83C\83R\83\93\82ª\83^\83X\83N\83o\81[\82É\8ec\82Á\82Ä\82µ\82Ü\82¤\81B\82È\82º\81H\81H
527 void __fastcall TDCHookMainForm::tmMenuCloseTimer(TObject *Sender)
528 {
529         Visible = true;
530         Visible = false;
531         ShowWindow( Application->Handle, SW_HIDE );
532         tmMenuClose->Enabled = false;
533 }
534 //---------------------------------------------------------------------------
535 void __fastcall TDCHookMainForm::tmNotifyTimer(TObject *Sender)
536 {
537         if ( NotifyForm ){
538                 tmNotify->Enabled = false;
539                 delete NotifyForm;
540                 NotifyForm = NULL;
541         }
542 }
543 //---------------------------------------------------------------------------
544 void __fastcall TDCHookMainForm::tmPopupTimer(TObject *Sender)
545 {
546         PostMessage( Handle, WM_POPUP, PopupLoc | (PopupMoveSend ? FLG_MOVESEND :  0), (LPARAM)PopupText );
547         PopupText = NULL;       // release ownership
548         tmPopup->Enabled = false;       // stop timer
549 }
550 //---------------------------------------------------------------------------
551 void __fastcall TDCHookMainForm::tmMouseMoveTimer(TObject *Sender)
552 {
553         tmMouseMove->Enabled = false;
554
555         if (!hDll)
556                 return;
557         //hDll->Capture();
558         hDll->CaptureAsync();
559 }
560 //---------------------------------------------------------------------------
561 void __fastcall TDCHookMainForm::tmMODIInstallCheckTimer(TObject *Sender)
562 {
563         if (MODIInstalled()){
564 #if 0
565                 Reboot();
566 #else
567                 // \8dÅ\8f\89\82Ìpopup\82Å\97\8e\82¿\82Ä\82µ\82Ü\82¤\81H
568                 if (!AMODIAvail && (CaptureMode & CM_IMAGE)){
569                         InitAMODI();
570                 }
571                 if (AMODIAvail){
572                         SetupConfig2();
573                 }
574 #endif
575         }
576 }
577 //---------------------------------------------------------------------------
578 void __fastcall TDCHookMainForm::tmMODINotifyTimer(TObject *Sender)
579 {
580         tmMODINotify->Enabled = false;
581         if (!AMODIRunable()){
582                 NotifyAMODI();
583         }
584 }
585 //---------------------------------------------------------------------------
586 void __fastcall TDCHookMainForm::tmReInitTimer(TObject *Sender)
587 {
588         // amodi.exe\82Ìlaunch\82É\94ñ\8fí\82É\8e\9e\8aÔ\82ª\82©\82©\82é\8fê\8d\87\82ª\82 \82é
589         // ex.\8cÃ\82¢PC\82Åstartup\82É\93o\98^\82µ\82Ä\82¢\82é\8fê\8d\87
590         //    \81¨input idle\82É\82È\82Á\82Ä\82àmain window\82Ì\90\90¬\82É\8e\9e\8aÔ\82ª\82©\82©\82Á\82Ä\82¢\82é\82Ì\82©\82à\82µ\82ê\82È\82¢
591         // AMODIAvail\82ªtrue\82É\82È\82é\82Ü\82Å\8f\89\8aú\89»\82ð\91±\82¯\82é
592         tmReInit->Enabled = false;
593         SetupAMODI();
594         if (AMODIAvail){
595                 SetupConfig2();
596         }
597 }
598 //---------------------------------------------------------------------------
599 // Mouse Events
600 //---------------------------------------------------------------------------
601 void __fastcall TDCHookMainForm::ImageMouseDown(TObject *Sender,
602           TMouseButton Button, TShiftState Shift, int X, int Y)
603 {
604         if ( BootUp ) return;
605         Capturing = true;
606         SetCapture( Handle );
607         CapPoint.x = X;
608         CapPoint.y = Y;
609 }
610 //---------------------------------------------------------------------------
611 void __fastcall TDCHookMainForm::ImageMouseMove(TObject *Sender,
612           TShiftState Shift, int X, int Y)
613 {
614         if ( Capturing ){
615                 POINT pt;
616                 GetCursorPos( &pt );
617                 Left = pt.x - CapPoint.x;
618                 Top = pt.y - CapPoint.y;
619         }
620 }
621 //---------------------------------------------------------------------------
622 void __fastcall TDCHookMainForm::ImageMouseUp(TObject *Sender,
623           TMouseButton Button, TShiftState Shift, int X, int Y)
624 {
625         if ( BootUp )
626                 Start();
627         Capturing = false;
628 }
629 //---------------------------------------------------------------------------
630 // User Functions
631 //---------------------------------------------------------------------------
632 void TDCHookMainForm::InitAMODI()
633 {
634         AMODIPath = Ini->ReadString(PFS_CONFIG, PFS_AMODIPATH, AMODIPath.c_str());
635         SetupAMODI();
636 }
637 void TDCHookMainForm::Start()
638 {
639         BootTimer->Enabled = false;
640 #ifndef _DEBUG
641         ShowWindow( Application->Handle, SW_HIDE );
642         Visible = false;
643         Width = 0;
644 #endif
645         if ( BootUp ){
646                 RegisterTrayIcon( true );
647                 miHookClick( this );
648                 BootUp = false;
649         }
650 }
651 //---------------------------------------------------------------------------
652 bool TDCHookMainForm::Hook()
653 {
654         if ( hDll ){
655                 DBW("Already hooked");
656                 return true;    // already loaded
657         }
658
659         bool use64 = Ini->ReadInteger(PFS_CONFIG, PFS_USE64, DEF_USE64);
660         hDll = new TDCHookLoader(use64);
661         if (!hDll->LoadHook(Handle)){
662                 DBW("Load failed");
663                 delete hDll;
664                 hDll = NULL;
665                 return false;
666         }
667
668         miHook->Enabled = false;
669         miUnhook->Enabled = true;
670
671         if (hDll->IsReady()){
672                 SetupConfig();
673                 extern HWND hwnd64;
674                 PostMessage(Handle, UM_SHORTCUT, SCINX_NOTIFY64, (LPARAM)hwnd64);
675         }
676
677         DBW("Hook OK");
678         
679         return true;
680 }
681 void TDCHookMainForm::Unhook()
682 {
683         if ( !hDll ) return;
684
685         hDll->UnloadHook();
686         delete hDll;
687         hDll = NULL;
688
689         miHook->Enabled = true;
690         miUnhook->Enabled = false;
691 }
692 //---------------------------------------------------------------------------
693 #ifdef _DEBUG
694 // text\82Ì\90æ\93ª\82ð(0,0)\82Æ\82µ\82½\8dÀ\95W\82Å\81Apos\82Ì\88Ê\92u\82É\82 \82étext\82Ì\95\8e\9a\88Ê\92u\82ð\95Ô\82·
695 int GetTextFromPoint( HDC hdc, const char *text, int pos )
696 {
697         int len = lstrlen(text);
698         int left = 0;
699         int right = len;
700         SIZE sz;
701         int loc;
702         for(;;){
703                 loc = (right + left)/2;
704                 if ( right - left <= 1 ){
705                         break;
706                 }
707                 GetTextExtentPoint32A( hdc, text, loc, &sz );
708 //              DBW("%08X %d %d %d %d", hdc, left, right, loc, sz.cx);
709                 if ( pos < sz.cx ){
710                         right = loc;
711                 } else {
712                         left = loc;
713                 }
714         }
715         return (right+left)/2;
716 }
717 int GetTextFromPoint( HDC hdc, const wchar_t *text, int pos )
718 {
719         int len = lstrlenW(text);
720         int left = 0;
721         int right = len;
722         SIZE sz;
723         int loc;
724         for(;;){
725                 loc = (right + left)/2;
726                 if ( right - left <= 1 ){
727                         break;
728                 }
729                 GetTextExtentPoint32W( hdc, text, loc, &sz );
730 //              DBW("%08X %d %d %d %d", hdc, left, right, loc, sz.cx);
731                 if ( pos < sz.cx ){
732                         right = loc;
733                 } else {
734                         left = loc;
735                 }
736         }
737         return (right+left)/2;
738 }
739 #endif
740 void TDCHookMainForm::EvCopyData(TMessage& msg )
741 {
742         COPYDATASTRUCT *cds = (COPYDATASTRUCT*)msg.LParam;
743         if ( !cds ){ return; }
744         switch ( cds->dwData ){
745                 case DCH_MOVESEND:
746                         //DBW("DCH_MOVESEND");
747                         // mouse move message
748                         EvMoveSend(msg.WParam==0);
749                         break;
750                 case DCH_START:
751                         CursorPoint = *(POINT*)cds->lpData;
752 #ifdef _DEBUG
753                         PaintBox->Canvas->FillRect( PaintBox->Canvas->ClipRect );
754 #endif
755                         if (PopupText){
756                                 delete[] PopupText;
757                                 PopupText = NULL;
758                         }
759                         break;
760                 case DCH_END:
761                 case DCH_END | DCH_MOVESEND:
762                         if ( PopupText ){
763                                 PopupMoveSend = cds->dwData & DCH_MOVESEND ? true : false;
764                                 PostMessage( Handle, WM_POPUP, PopupLoc | (PopupMoveSend ? FLG_MOVESEND : 0), (LPARAM)PopupText );
765                                 if (OCRTextForm) OCRTextForm->SetText(PopupText);
766                                 PopupText = NULL;       // release ownership
767                         }
768                         break;
769                 case DCH_HITTEXT1:      // single char
770                 {
771                         DBW("DCH_HITTEXT1");
772                         if (PopupText)
773                                 delete[] PopupText;
774 #ifdef USE_UNICODE
775                         // ANSI -> Unicode
776                         //*+++ \93®\8dì\96¢\8am\94F 2002.12.4
777                         PopupText = new tchar[ cds->cbData*2 + 1 ];
778                         // \91O\94¼\95\94\95ª
779                         PopupLoc = MultiByteToWideChar( CP_ACP, 0,
780                                 (LPCSTR)cds->lpData, msg.WParam, PopupText, cds->cbData*2 );
781                         // \8cã\94¼\95\94\95ª
782                         int r = MultiByteToWideChar( CP_ACP, 0,
783                                 &((char*)cds->lpData)[msg.WParam], cds->cbData-msg.WParam, &PopupText[PopupLoc], cds->cbData-PopupLoc );
784                         PopupText[PopupLoc+r] = '\0';
785 #else   // !USE_UNICODE
786                         PopupText = new tchar[ cds->cbData + 1 ];
787                         memcpy( PopupText, cds->lpData, cds->cbData );
788                         PopupText[cds->cbData] = '\0';
789                         PopupLoc = msg.WParam;
790 #ifdef _DEBUG
791                         Memo->Lines->Add( PopupText );
792                         edFound->Text = PopupText + msg.WParam;
793                         TestTimer->Enabled = true;
794                         if ( DCDebug ){
795                                 char *p = (char*)DCDebug( );
796                                 memcpy( share, p, COMPSIZE );
797                         }
798 #endif
799 #endif
800                 }
801                         break;
802                 case DCH_HITTEXT2:      // wide char
803                 {
804                         DBW("DCH_HITTEXT2");
805                         if (PopupText)
806                                 delete[] PopupText;
807 #ifdef USE_UNICODE
808                         PopupText = new tchar[ cds->cbData + 1 ];
809                         memcpy( PopupText, cds->lpData, cds->cbData );
810                         PopupText[cds->cbData/sizeof(tchar)] = '\0';
811                         PopupLoc = msg.WParam;
812 #else   // !USE_UNICODE
813                         // Unicode -> ANSI
814                         //*+++ \93®\8dì\96¢\8am\94F 2002.12.4
815                         PopupText = new tchar[ cds->cbData + 1 ];
816                         // \91O\94¼\95\94\95ª
817                         BOOL defchar;
818                         PopupLoc = WideCharToMultiByte( CP_ACP, 0,
819                                 (wchar_t*)cds->lpData, msg.WParam,
820                                 PopupText, cds->cbData, 0, &defchar );
821                         // \8cã\94¼\95\94\95ª
822                         int r = WideCharToMultiByte( CP_ACP, 0,
823                                 &((wchar_t*)cds->lpData)[msg.WParam], (cds->cbData>>1)-msg.WParam,
824                                 &PopupText[PopupLoc], cds->cbData-PopupLoc, 0, &defchar );
825                         PopupText[PopupLoc+r] = '\0';
826 #endif
827                 }
828                         break;
829 #ifdef _DEBUG
830                 case DCH_EXTTEXTOUTA:
831                 case DCH_EXTTEXTOUTW:
832                 {
833                         EMREXTTEXTOUTW *emr = (EMREXTTEXTOUTW*)cds->lpData;
834                         wchar_t *p = (wchar_t*) ( ((char*)emr) + emr->emrtext.offString );
835                         char *buf = NULL;
836 #if 0
837                         char b[200];
838                         sprintf(b,"exScale=%f eyScale=%f ptlReference=(%d,%d)",emr->exScale, emr->eyScale, emr->emrtext.ptlReference.x, emr->emrtext.ptlReference.y );
839                         DBW(b);
840 #endif
841                         if ( cds->dwData == DCH_EXTTEXTOUTW ){
842                                 buf = new char[ emr->emrtext.nChars * 2 ];
843                                 memset( buf, 0, emr->emrtext.nChars*2 );
844                                 WideCharToMultiByte( CP_ACP, 0, p, emr->emrtext.nChars, buf, emr->emrtext.nChars * 2, NULL, NULL );
845                         }
846                         const char *text = buf ? buf : (char*)p;
847                         Memo->Lines->Add( text );
848                         PaintBox->Canvas->TextOut( emr->rclBounds.left, emr->rclBounds.top, text );
849
850                         if ( PtInRect( (RECT*)&emr->rclBounds, CursorPoint ) ){
851                                 int loc = GetTextFromPoint( (HDC)msg.WParam, text, CursorPoint.x - emr->rclBounds.left );
852                                 if ( loc != -1 ){
853                                         edFound->Text = text + loc;
854                                 }
855                         }
856                         if ( buf )
857                                 delete[] buf;
858                 }
859                         break;
860 #endif
861                 case DCH_MENU:
862                         DokoPopMenu( false );
863                         break;
864                 case DCH_TOGGLE:
865                         PostMessage( Handle, WM_TOGGLE, 0, 0 );
866                         break;
867                 case WMCD_EXISTCHECK:   // exist check
868                         if ( cds->cbData != strlen(APPNAME)+1 ){
869                                 msg.Result = false;
870                                 return;
871                         }
872                         msg.Result = (memcmp( cds->lpData, APPNAME, strlen(APPNAME)+1 ) == 0);
873                         return;
874                 case DCH_LAUNCH_AMODI:
875                         SetupAMODI();
876                         //Reboot();             // AMODI.exe\8dÄ\8bN\93®\82Å\82Í\89ð\8c\88\82Å\82«\82È\82¢\82½\82ß
877                         break;
878         }
879         return;
880 }
881 //---------------------------------------------------------------------------
882 bool WaitTransaction( TDdeClientConv *dde )
883 {
884 #if 1
885         for ( int i=0;i<100000;i++ ){
886                 Application->ProcessMessages();
887                 if ( !dde->WaitStat ){
888 //                      DBW("DCHook:Wait OK");
889                         return true;
890                 }
891         }
892         DBW("DCHook:Wait failure");
893         return false;
894 #else
895         return true;
896 #endif
897 }
898 // ANSI\82Å\93n\82·\8fê\8d\87
899 bool DdePoke( TDdeClientConv *dde, AnsiString Item, AnsiString Data )
900 {
901 #ifdef USE_UNICODE
902         int ansilen = Data.Length();
903         wchar_t *buf = new wchar_t[ansilen*2+1];
904         int len = MultiByteToWideChar( CP_ACP, 0,
905                 (LPCSTR)Data.c_str(), ansilen, buf, ansilen*2 );
906         buf[len] = '\0';
907         bool r = DdePoke( dde, Item, (wchar_t*)buf );
908         delete[] buf;
909         return r;
910 #else   // !USE_UNICODE
911         HSZ hszItem = DdeCreateStringHandle(ddeMgr->DdeInstId, Item.c_str(), CP_WINANSI );
912         if ( !hszItem ) return false;
913         HDDEDATA hszDat = DdeCreateDataHandle( ddeMgr->DdeInstId, Data.c_str(), Data.Length() + 1,
914                 0, hszItem, dde->DdeFmt, 0);
915         bool r = false;
916         if ( hszDat ){
917                 HDDEDATA hdata = DdeClientTransaction( (LPBYTE)hszDat, (DWORD)-1, (HCONV)dde->Conv, hszItem,
918                         dde->DdeFmt, XTYP_POKE, 10000, NULL);
919                 if (hdata || DdeGetLastError(ddeMgr->DdeInstId) != DMLERR_NO_ERROR){
920                         r = true;
921                         if (hdata)
922                                 DdeFreeDataHandle( hdata );
923                 }
924         }
925         DdeFreeStringHandle(ddeMgr->DdeInstId, hszItem);
926         return r;
927 #endif
928 }
929 #ifdef USE_UNICODE
930 // Unicode\82Å\93n\82·\8fê\8d\87
931 bool DdePoke( TDdeClientConv *dde, AnsiString Item, const wchar_t *Data )
932 {
933         // Item\96¼\82ÍANSI\81A\83f\81[\83^\82ÍUNICODE //
934         int ddeFmt = /*dde->DdeFmt*/CF_UNICODETEXT;
935         HSZ hszItem = DdeCreateStringHandle(ddeMgr->DdeInstId, Item.c_str(), CP_WINANSI );
936         if ( !hszItem ) return false;
937         HDDEDATA hszDat = DdeCreateDataHandle( ddeMgr->DdeInstId, (LPBYTE)Data, (_tcslen(Data)+1)*sizeof(wchar_t),
938                 0, hszItem, ddeFmt, 0);
939         bool r = false;
940         if ( hszDat ){
941                 HDDEDATA hdata = DdeClientTransaction( (LPBYTE)hszDat, (DWORD)-1, (HCONV)dde->Conv, hszItem,
942                         ddeFmt, XTYP_POKE, 10000, NULL);
943                 if (hdata || DdeGetLastError(ddeMgr->DdeInstId) != DMLERR_NO_ERROR){
944                         r = true;
945                         if (hdata)
946                                 DdeFreeDataHandle( hdata );
947                 }
948         }
949         DdeFreeStringHandle(ddeMgr->DdeInstId, hszItem);
950         return r;
951 }
952 bool DdeRequest( TDdeClientConv *dde, AnsiString Item, char *Data, int &ioDataLen )
953 {
954         const int ddeFmt = /*dde->DdeFmt*/CF_UNICODETEXT;
955         HSZ hszItem = DdeCreateStringHandle(ddeMgr->DdeInstId, Item.c_str(), CP_WINANSI );
956         if ( !hszItem ) return false;
957         bool r = false;
958         HDDEDATA hdata = DdeClientTransaction( NULL, 0, (HCONV)dde->Conv, hszItem, ddeFmt, XTYP_REQUEST, 10000, NULL);
959         if (hdata || DdeGetLastError(ddeMgr->DdeInstId) != DMLERR_NO_ERROR){
960                 r = true;
961                 if (hdata){
962                         ioDataLen = DdeGetData(hdata, (LPBYTE)Data, ioDataLen, 0);
963                         DdeFreeDataHandle( hdata );
964                 } else {
965                         Data[0] = '0';
966                         ioDataLen = 0;
967                 }
968         }
969         DdeFreeStringHandle(ddeMgr->DdeInstId, hszItem);
970         return r;
971 }
972 #endif
973 TDdeClientConv *TDCHookMainForm::OpenPdic( const char *topic )
974 {
975         TDdeClientConv *PdicDde = new TDdeClientConv( this );
976
977         PdicDde->ConnectMode = ddeManual;
978         static int entry = 0;
979         PdicDde->Name = AnsiString("PdicDde") + (++entry);
980         PdicDde->ServiceApplication = DDE_SERVICE_NAME;
981         if ( !PdicDde->SetLink( DDE_SERVICE_NAME, topic ) ){
982                 DBW("DCHook:Cannot SetLink");
983                 delete PdicDde;
984                 return NULL;
985         }
986         if ( !PdicDde->OpenLink( ) ){   // \82±\82±\82ª\92x\82¢\81I\81I
987                 // PDIC auto launch
988                 if ( LaunchPdic() ){
989                         for(int i=0;i<OPEN_RETRY;i++){
990                                 if ( PdicDde->OpenLink() ){
991                                         return PdicDde;
992                                 }
993                                 Sleep(OPEN_WAITTIME);
994                         }
995                 }
996                 DBW("PDIC\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ(OpenPdic)");
997                 Application->MessageBox( "PDIC\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ(OpenPdic)", APPNAME, MB_OK );
998                 delete PdicDde;
999                 return NULL;
1000         }
1001         return PdicDde;
1002 }
1003 #ifdef USE_UNICODE
1004 static const TCHAR *clsname = TEXT("TPdicMain.UnicodeClass");
1005 #else
1006 static const TCHAR *clsname = TEXT(DDE_SERVICE_NAME);
1007 #endif
1008 static const TCHAR *winname = NULL;
1009 HWND TDCHookMainForm::FindPdic( )
1010 {
1011         HWND hWin = FindWindow( clsname, winname );
1012         if ( !hWin ){
1013                 // PDIC auto launch
1014                 if ( LaunchPdic() ){
1015                         hWin = FindWindow( clsname, winname );
1016                         if ( !hWin ){
1017                                 DBW("PDIC\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ(FindPdic)");
1018                                 Application->MessageBox( "PDIC\82ª\8c©\82Â\82©\82è\82Ü\82¹\82ñ(FindPdic)", APPNAME, MB_OK );
1019                                 return NULL;
1020                         }
1021                 }
1022         }
1023         return hWin;
1024 }
1025 #if !USE_DDE
1026 LRESULT TDCHookMainForm::SendCopyData( HWND hwnd, int message, const char *str )
1027 {
1028         COPYDATASTRUCT cds;
1029         cds.dwData = message;
1030         cds.lpData = (LPSTR)str;
1031         cds.cbData = lstrlen(str)+1;
1032         SendMessage( hwnd, WM_COPYDATA, (WPARAM)Handle, (LPARAM)&cds );
1033 }
1034 #endif
1035 void TDCHookMainForm::ClosePdic( TDdeClientConv *dde )
1036 {
1037         dde->CloseLink();
1038         delete dde;
1039 }
1040 // XX.XX.XXXX (hex) 1+1+2 byte\8d\\90¬
1041 int TDCHookMainForm::GetPdicVersion()
1042 {
1043         TDdeClientConv *PdicDde = OpenPdic("PDIC");
1044         if (!PdicDde) return 0;
1045         int version = 0;
1046 #ifdef USE_UNICODE
1047         char buf[40];
1048         if (DdeRequest(PdicDde, "GetVersion", buf, sizeof(buf))){
1049                 wchar_t *str = (wchar_t*)buf;
1050                 version = _wtoi( str ) << 24;
1051                 const wchar_t *p = wcschr( str, '.' );
1052                 if (p){
1053                         version |= _wtoi( p+1 ) << 16;
1054                         p = wcschr( p+1, '.' );
1055                         if (p){
1056                                 version |= _wtoi( p+1 );
1057                         }
1058                 }
1059                 //DBW("version: %X", version);
1060         }
1061 #endif
1062         ClosePdic( PdicDde );
1063         return version;
1064 }
1065 // click_pos: mouse click\82³\82ê\82½text\8fã\82Ì\95\8e\9a\88Ê\92u(text\90æ\93ª\82©\82ç\82Ìoffset)
1066 bool TDCHookMainForm::DoPopup( const tchar *text, int click_pos, const tchar *prevtext, bool movesend )
1067 {
1068         static int ct = 0;
1069         if ( ct >= 1 ){
1070                 if (PopupText){
1071                         // already pending
1072                         DBW("Reentrant!!!!!");
1073                         return true;
1074                 }
1075                 HWND hwnd = FindPopupWindow( );
1076                 if (hwnd){
1077                         HWND hwndParent = GetParent( hwnd );
1078                         if (hwndParent){
1079                                 DBW("Parent exist!!!!");
1080                                 hwnd = hwndParent;
1081                         }
1082                         DBW("Retry again:%d:%08X",ct,hwnd);
1083                         // \95K\82¸PostMessage()\82Åclose\82·\82é\82±\82Æ\81B
1084                         // CloseWindow()\82Å\82ÍPopup Winodow\82Ì\8f\89\8aú\89»\92\86\82É
1085                         // close\8f\88\97\9d\82ð\8eÀ\8ds\82µ\82Ä\82µ\82Ü\82¢\81A
1086                         // popup window\82ª\82¨\82©\82µ\82È\8fó\91Ô\82É\82Í\82¢\82Á\82Ä\82µ\82Ü\82¤\8fê\8d\87\82ª\82 \82é
1087                         PostMessage( hwnd, WM_CLOSE, 0, 0 );
1088                         return false;
1089                 } else {
1090                         if (ct >= 1 ){
1091                                 DBW("Not found popup window");
1092                                 if (DoPopupRetry++ > 10){
1093                                         DoPopupRetry = 0;
1094                                         return true;    // abort
1095                                 } else {
1096                                         return false;   // retry
1097                                 }
1098                         }
1099                 }
1100         }
1101         DoPopupRetry = 0;
1102         ct++;
1103
1104 #if USE_DDE
1105         // Windows9x\82Å\82Í\81ADDE transaction\82ª\92x\82¢\82Æ\82«\82ª\82 \82é
1106         // why? - because of 24bit OS:-)
1107         // ->\82Æ\8ev\82Á\82Ä\81AWM_COPYDATA version\82ð\8dì\82Á\82Ä\82¢\82½\82ç\91¬\82­\82È\82Á\82½\81H\81H\81H
1108         // ->WM_COPYDATA\89» project\82Í\92\86\92f
1109         TDdeClientConv *PdicDde;
1110         bool r;
1111
1112         if (movesend){
1113                 // incremental search
1114                 PdicDde = OpenPdic("Simulate");
1115                 if (!PdicDde){
1116                         ct--;
1117                         return true;
1118                 }
1119                 r = DdePoke(PdicDde, "InputWord3", text);
1120                 if (!r){
1121                         DBW("PDIC DDE : InputWord3 failure");
1122                         delete PdicDde;
1123                         ct--;
1124                         return true;
1125                 }
1126         } else {
1127                 // popup
1128                 if (GroupOpen){
1129                         PdicDde = OpenPdic( "Simulate" );
1130                         if (PdicDde){
1131                                 DdePoke( PdicDde, "Open", GroupName );
1132                                 PdicDde->CloseLink();
1133                                 delete PdicDde;
1134                         }
1135                 }
1136                 PdicDde = OpenPdic( "Dictionary" );
1137                 if ( !PdicDde ){
1138                         ct--;
1139                         return true;
1140                 }
1141
1142                 r = DdePoke( PdicDde, "Open", "" );
1143                 if ( !r ){
1144                         DBW("PDIC DDE : Open failure");
1145                         PdicDde->CloseLink();
1146                         delete PdicDde;
1147                         ct--;
1148                         if ( GroupOpen ){
1149                                 static int ct = 0;
1150                                 ct++;
1151                                 if ( ct == 1 ){
1152                                         Application->MessageBox(
1153                                                 "\8e«\8f\91\83O\83\8b\81[\83v\82ª\8aJ\82¯\82Ü\82¹\82ñ\r"
1154                                                 "DokoPop!\82Å\81u\8e«\8f\91\83O\83\8b\81[\83v\8ew\92è\81v\82ð\97L\8cø\82É\82µ\82Ä\82¢\82é\8fê\8d\87\82Í\81A\82·\82Å\82ÉPDIC\96{\91Ì\82Å\83I\81[\83v\83\93\82³\82ê\82Ä\82¢\82é\8e«\8f\91\82Æ\8b¤\97L\88á\94½\82ð\8bN\82±\82µ\82Ä\82¢\82é\89Â\94\\90«\82ª\82 \82è\82Ü\82·\r"
1155                                                 "DokoPop!\82ÆPDIC\96{\91Ì\82Å\8eg\97p\82µ\82Ä\82¢\82é\8e«\8f\91\82É\93¯\88ê\82Ì\82à\82Ì\82ª\82È\82¢\82©\92²\82×\82Ä\82­\82¾\82³\82¢\r"
1156                                                 "\82à\82µ\82 \82Á\82½\8fê\8d\87\82Í\93o\98^\8bÖ\8e~\82È\82Ç\8b¤\97L\82Å\82«\82é\82æ\82¤\82È\8fó\91Ô\82É\82µ\82Ä\82­\82¾\82³\82¢\r"
1157                                                 "\82±\82Ì\83\81\83b\83Z\81[\83W\82Ì\88Ó\96¡\82ª\82í\82©\82ç\82È\82¢\8fê\8d\87\82Í\81A\81u\8e«\8f\91\83O\83\8b\81[\83v\8ew\92è\81v\8b@\94\\82ð\8eg\82í\82È\82¢\82Ù\82¤\82ª\88À\91S\82Å\82·"
1158                                                 ,
1159                                                 APPNAME, MB_OK );
1160                                 } else {
1161                                         SetForegroundWindow( Handle );
1162                                 }
1163                                 ct--;
1164                         }
1165                         return true;
1166                 }
1167                 if ( CtrlClose )
1168                         DdePoke( PdicDde, "PopupSearchConfig", "c1" );  // Ctrl close
1169         //      Sleep(1000);
1170                 DdePoke( PdicDde, "PopupSearchConfig", "o1w1" );        // overlap window and no wait transaction
1171                 if ( prevtext && (prevtext != text) ){
1172                         //DBW("prevtext="FMTS,prevtext);
1173 #if 1
1174                         int len = _tcslen(prevtext);
1175                         tchar *buf = new tchar[len+10];
1176                         _itow( STR_DIFF(text, prevtext) + click_pos, buf, 10 ); // \83N\83\8a\83b\83N\88Ê\92u
1177                         tchar *dp = buf + _tcslen(buf);
1178                         *dp++ = ',';
1179                         wcscpy( dp, prevtext );
1180                         DdePoke( PdicDde, "PopupSearch3", buf );
1181         //              ExecuteMacro( "PopupSearch3", true );
1182                         delete[] buf;
1183 #else
1184                         DdePoke( PdicDde, "PopupSearch2", (tchar*)prevtext );
1185         //              ExecuteMacro( "PopupSearch2", true );
1186 #endif
1187                         WaitTransaction( PdicDde );
1188                 } else {
1189                         //DBW("text="FMTS,text);
1190                         DdePoke( PdicDde, "PopupSearch", (tchar*)text );
1191         //              PdicDde->ExecuteMacro( "PopupSearch", true );
1192                         WaitTransaction( PdicDde );
1193                 }
1194                 DdePoke( PdicDde, "Close", "" );
1195         }
1196         ClosePdic( PdicDde );
1197 #else   // !USE_DDE
1198                 // WM_COPYDATA\82É\82æ\82é\95û\96@(\82Ü\82¾document\89»\82³\82ê\82Ä\82¢\82È\82¢\95û\96@(Ver.4.30)
1199                 // PDIC/W32 Ver.4.22\81`\82É\91Î\89\9e
1200                 // \82½\82¾\82µ\81AVer.4.29\82Ü\82Å\82Í\81AWMCD_POPUPSEARCH\82ÆWMCD_POPUPSEARCH2\82Í\93¯\82
1201
1202         // WM_COPYDATA code //
1203         // \88È\89º\82Ì\90\94\92l\82Í\8f«\97\88\95Ï\82í\82é\89Â\94\\90«\82ª\82 \82é(undocumented) //
1204         #define WMCD_GETVERSION         0x0001
1205         #define WMCD_CHECKOPEN          0x0010
1206         #define WMCD_AUTOSEARCH         0x0020
1207         #define WMCD_AUTOSEARCHMODE     0x0021
1208
1209         #define WMCD_ISOPENED                   0x0080
1210         #define WMCD_CLOSE                              0x0081
1211
1212         #define WMCD_POPUPSEARCH                0x0100
1213         #define WMCD_POPUPSEARCH2               0x0101
1214         #define WMCD_POPUPSEARCHPOINT   0x0102
1215         #define WMCD_POPUPSEARCHCONFIG  0x0103
1216         #define WMCD_POPUPSEARCHDIALOG  0x0104
1217         #define WMCD_POPUPSEARCHWINDOW  0x0105
1218
1219         #define WMCD_SPELLCHECK                 0x0110
1220
1221         HWND hwnd = FindPdic();
1222         if ( !hwnd ){
1223                 ct--;
1224                 return;
1225         }
1226
1227         bool r;
1228         if ( CtrlClose )
1229                 SendCopyData( hwnd, WMCD_POPUPSEARCHCONFIG, "c1" );
1230         POINT pt;
1231         GetCursorPos( &pt );
1232         char buf[20];
1233         wsprintf( buf, "%d,%d", pt.x, pt.y );
1234         SendCopyData( hwnd, WMCD_POPUPSEARCHPOINT, buf );
1235         if ( prevtext && (prevtext != text) ){
1236                 DBW("prevtext=%s",prevtext);
1237                 SendCopyData( hwnd, WMCD_POPUPSEARCH2, prevtext );
1238         } else {
1239                 DBW("text=%s",text);
1240                 SendCopyData( hwnd, WMCD_POPUPSEARCH, text );
1241         }
1242         SendCopyData( hwnd, WMCD_CLOSE, "" );
1243 #endif  // !USE_DDE
1244         ct--;
1245         DBW("DCHook:Exit Popup:%d",ct);
1246
1247 #if DETACHRELEASE
1248         if ( EnablePopup ){
1249                 miUnhookClick( this );
1250                 miHookClick( this );
1251         }
1252 #endif
1253         return true;
1254 }
1255 //---------------------------------------------------------------------------
1256 // EvPopup
1257 // WParam : text location & FLG_MOVESEND
1258 // LParam : text pointer (must be freed when done)
1259 void TDCHookMainForm::EvPopup(TMessage &msg)
1260 {
1261         //DBW("EvPopup");
1262         if (!msg.LParam)
1263                 return;
1264
1265         int pdicVer = GetPdicVersion();
1266         const int numPrev = pdicVer >= 0x050A0018 ? 2 : 1;      // ver.5.10.24\88È\8fã
1267                 
1268         tchar *text = (tchar*)msg.LParam;
1269         int loc = msg.WParam & ~FLG_MOVESEND;
1270         bool movesend = msg.WParam & FLG_MOVESEND ? true : false;
1271         
1272         int start, end;
1273         int prevstart;
1274         if ( !GetWord( text, loc, start, end, prevstart, true, 10, true, IgnoreJ, numPrev ) ){
1275                 // no words
1276                 delete[] text;
1277                 return;
1278         }
1279 #ifdef _DEBUG
1280         edWord->Text = text + start;
1281         edPrev->Text = loc + prevstart;
1282 #endif
1283
1284         if (DoPopup( text + start, loc - start, text + prevstart, movesend )){
1285                 // done
1286                 delete[] text;
1287         } else {
1288                 // retry again
1289                 if (PopupText)
1290                         delete[] PopupText;     // \82 \82Æ\82É\97\88\82½\82Ù\82¤\82ð\97D\90æ\82·\82é
1291                 PopupText = text;
1292                 PopupLoc = loc;
1293                 PopupMoveSend = movesend;
1294                 tmPopup->Enabled = true;        // start timer for delayed popup
1295         }
1296         //DBW("EvPopup - end");
1297 }
1298 void TDCHookMainForm::EvMoveSend(TMessage &msg)
1299 {
1300         EvMoveSend(msg.WParam==0);
1301 }
1302 void TDCHookMainForm::EvMoveSend(bool enable)
1303 {
1304         tmMouseMove->Enabled = false;
1305         if (enable){
1306                 tmMouseMove->Enabled = true;
1307         }
1308 }
1309 void TDCHookMainForm::RegisterTrayIcon( bool flag )
1310 {
1311   NOTIFYICONDATA m_tnid;  //\82±\82ê\82Í*.h\82Å\92è\8b`\82µ\82Ä\82¨\82­
1312
1313   m_tnid.cbSize = sizeof(NOTIFYICONDATA);
1314   m_tnid.hWnd = Handle;
1315   m_tnid.uID = 1;
1316   m_tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
1317   m_tnid.uCallbackMessage = WM_NOTIFYICON;
1318   // Get small icon from me
1319   HICON hIconSm;
1320   HICON hIcon;
1321   ExtractIconEx( Application->ExeName.c_str(), -2, &hIcon, &hIconSm, 1 );
1322   m_tnid.hIcon = hIconSm;
1323   lstrcpy(m_tnid.szTip, APPNAME );
1324   Shell_NotifyIcon( flag ? NIM_ADD : NIM_DELETE, &m_tnid);
1325 }
1326 void TDCHookMainForm::EvNotifyIcon(TMessage &msg)
1327 {
1328         //UINT uID = (UINT) msg.WParam;
1329         UINT uMouseMsg = (UINT) msg.LParam;
1330         if (uMouseMsg == WM_LBUTTONDBLCLK)
1331         {
1332                 miOptionClick( this );
1333         }
1334         else if (uMouseMsg == WM_RBUTTONDOWN)
1335         {
1336                 DokoPopMenu( true );
1337         }
1338 }
1339 //---------------------------------------------------------------------------
1340 void TDCHookMainForm::SaveConfig()
1341 {
1342         Ini->WriteInteger( PFS_CONFIG, PFS_GROUPOPEN, GroupOpen );
1343         Ini->WriteString( PFS_CONFIG, PFS_GROUPNAME, GroupName.c_str() );
1344         Ini->WriteInteger( PFS_CONFIG, PFS_CTRLCLOSE, CtrlClose );
1345         Ini->WriteInteger( PFS_CONFIG, PFS_IGNOREJ, IgnoreJ );
1346         Ini->WriteInteger( PFS_CONFIG, PFS_BANNER, Banner );
1347 }
1348 void TDCHookMainForm::OpenDicGroup( const char *name )
1349 {
1350         TDdeClientConv *dde = OpenPdic( PFS_PDIC );
1351         if ( !dde )
1352                 return;
1353         // \8e«\8f\91\83O\83\8b\81[\83v\83I\81[\83v\83\93\8f\88\97\9d //
1354         if ( name[0] == '&' )
1355                 name++;
1356         DdePoke(dde, "OpenGroup", (tchar*)mustr(name));
1357         ClosePdic( dde );
1358 }
1359 //---------------------------------------------------------------------------
1360 // DokoPop\82Ì\90Ý\92è
1361 void TDCHookMainForm::SetupConfig()
1362 {
1363         EnableClickOnly( miClickOnly->Checked );
1364         if (hDll){
1365                 hDll->Config( -1, KA_POPUP,
1366                         Ini->ReadInteger( PFS_CONFIG, PFS_POPUPKEY, DEF_POPUPKEY ) );
1367                 hDll->Config( -1, KA_TOGGLE,
1368                         Ini->ReadInteger( PFS_CONFIG, PFS_TOGGLEKEY, DEF_TOGGLEKEY ) );
1369
1370                 SetupConfig2();
1371         }
1372         SetupAMODI();
1373 }
1374 void TDCHookMainForm::SetupConfig2()
1375 {
1376         if (!hDll)
1377                 return;
1378
1379         TDCHConfig cfg;
1380         memset(&cfg, 0, sizeof(cfg));
1381         cfg.UseAMODI = AMODIAvail && (CaptureMode & CM_IMAGE);
1382         cfg.OnlyAMODI = AMODIAvail && !(CaptureMode & CM_TEXT);
1383         cfg.MoveSend = MouseIncSrch;
1384         //cfg.OnlyImage = 1;    //TODO:
1385         if (AMODIPath.data()){
1386                 strncpy(cfg.AMODIPath, AMODIPath.c_str(), sizeof(cfg.AMODIPath)-1);
1387         }
1388
1389         int dpiDetect = Ini->ReadInteger(PFS_CONFIG, PFS_DPI_DETECT, 1);
1390         if (dpiDetect){
1391 #if DPI_DETECT
1392                 cfg.ScaleX = GetMonitorScale();
1393 #endif
1394         } else {
1395                 cfg.ScaleX = Ini->ReadInteger(PFS_CONFIG, PFS_SCALE, 0);
1396         }
1397         cfg.ScaleY = cfg.ScaleX;
1398         hDll->Config2(&cfg);
1399 }
1400 void TDCHookMainForm::SetupAMODI()
1401 {
1402         if (AMODIPath.data()){
1403                 AMODIAvail = true;
1404         } else {
1405                 HWND hwnd = FindAMODI();
1406                 if (hwnd){
1407                         AMODIAvail = true;
1408                 } else {
1409                         AMODIAvail = LaunchAMODI();
1410                         if (!AMODIAvail){
1411                                 HWND hwnd = FindAMODI();
1412                                 if (hwnd)
1413                                         AMODIAvail = true;
1414                                 else
1415                                         tmReInit->Enabled = true;       // retry later
1416                         }
1417                 }
1418         }
1419         if (AMODIAvail){
1420                 tmMODIInstallCheck->Enabled = false;
1421         }
1422 }
1423 void TDCHookMainForm::EnableClickOnly( bool enable )
1424 {
1425         if (hDll)
1426                 hDll->Config( enable, 0, 0 );
1427 }
1428 void TDCHookMainForm::DokoPopMenu( bool all )
1429 {
1430 //      Width = 0;
1431         SetForegroundWindow( Handle );
1432         POINT pt;
1433         GetCursorPos( &pt );
1434         miEnablePopup->Visible = all;
1435         miReload->Visible = !all;
1436         miClose->Visible = !all;
1437         miExit2->Visible = all;
1438         pmTrayIcon->TrackButton = tbRightButton;
1439         pmTrayIcon->Popup( pt.x, pt.y );
1440         MoveToTop( Handle );
1441 //      MoveToTop( pmTrayIcon->WindowHandle );
1442 }
1443 void TDCHookMainForm::MenuClosed()
1444 {
1445         Visible = false;
1446         ShowWindow( Application->Handle, SW_HIDE );
1447         tmMenuClose->Enabled = true;
1448 }
1449 void TDCHookMainForm::EvToggle( TMessage &msg )
1450 {
1451         miClickOnlyClick( this );
1452         ShowNotify();
1453 }
1454 void TDCHookMainForm::EvShortcut( TMessage &msg )
1455 {
1456         switch (msg.WParam){
1457                 case SCINX_NOTIFY64:
1458                         DBW("SCINX_NOTIFY64:%08X %08X", msg.LParam, hDll);
1459                         if (hDll){
1460                                 hDll->Notify64(msg.LParam);
1461                                 SetupConfig();
1462                         }
1463                         break;
1464         }
1465 }
1466 void TDCHookMainForm::EvGetVersion( TMessage &msg )
1467 {
1468         msg.Result = VersionValue;
1469 }
1470 //---------------------------------------------------------------------------
1471 // \89E\83N\83\8a\83b\83N\8c\9f\8dõON/OFF\95\\8e¦
1472 void TDCHookMainForm::ShowNotify()
1473 {
1474         POINT pt;
1475         GetCursorPos( &pt );
1476         if ( !NotifyForm ){
1477                 NotifyForm = new TNotifyForm( this );
1478         } else {
1479                 NotifyForm->Visible = false;
1480         }
1481         NotifyForm->enable = miClickOnly->Checked;
1482         NotifyForm->Left = pt.x + 8;
1483         NotifyForm->Top = pt.y + 8;
1484         NotifyForm->Setup();
1485         NotifyForm->Show();
1486         SetWindowPos( Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1487         SetWindowPos( NotifyForm->Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1488         tmNotify->Enabled = false;
1489         tmNotify->Enabled = true;
1490 }
1491 void TDCHookMainForm::NotifyAMODI()
1492 {
1493         MODINotifyDialog = new TMODINotifyDialog(this);
1494         MODINotifyDialog->ShowModal();
1495         if (MODINotifyDialog->LinkClicked || AMODIRunable()){
1496                 tmMODIInstallCheck->Enabled = true;
1497         }
1498         delete MODINotifyDialog;
1499 }
1500 void TDCHookMainForm::Reboot()
1501 {
1502         ::Reboot = true;
1503         Close();
1504 }
1505 void GetGroupList(TMyIni &ini, TStringList &list)
1506 {
1507         AnsiString s = ini.ReadString("Group", "::GroupNames::", "");
1508         if (s.IsEmpty()){
1509                 // for old version (not work correctly)
1510                 ini.ReadValues( "Group", &list);
1511         } else {
1512                 const TCHAR *p = _tcstok(s.c_str(), _T("\t"));
1513                 while (p){
1514                         list.Add( p );
1515                         p = _tcstok(NULL, _T("\t"));
1516                 }
1517         }
1518 }
1519