OSDN Git Service

first commit
[dokopop/dokopop.git] / amodi / amodi / MainForm.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Text.RegularExpressions;
9 using System.Windows.Forms;
10 using System.IO;
11 using System.Runtime.InteropServices;
12
13 namespace amodi
14 {
15     public partial class AutoMODIMainForm : Form
16     {
17
18                 const int MARGIN_UNDER_CLICK = 2;       // 次の行までの空白
19
20         const int WM_COPYDATA = 0x4A;
21         const int WM_APP = 0x8000;
22         const int WM_AMODI = (WM_APP + 0x400);
23         const int WM_EXEC_OCR = (WM_APP + 0x410);
24
25         // WM_COPYDATA command
26         const int WMCD_EXISTCHECK = 0x4000;
27                 const int WMCD_SETPOINT = 0x4001;
28                 const int WMCD_RESTORE_WINDOW = 0x4002;
29
30
31         //[StructLayout(LayoutKind.Sequential)]
32         private struct COPYDATASTRUCT
33         {
34             public IntPtr dwData;
35             public int cbData;
36             public IntPtr lpData;
37         }
38
39         public struct COPYDATASTRUCT_send {
40             public Int32 dwData;        //送信する32ビット値
41             public Int32 cbData;    //lpDataのバイト数
42             public string lpData;   //送信するデータへのポインタ(0も可能)
43         }
44
45         [DllImport("user32.dll", SetLastError = true)]
46         private static extern int PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
47         [DllImport("user32.dll", SetLastError = true)]
48         private static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, ref COPYDATASTRUCT_send lparam);
49         [DllImport("User32.dll", EntryPoint = "FindWindow")]
50         public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
51
52         MODI.Document md;
53         System.IO.FileSystemWatcher fsw;
54         Queue<string> FileNameQue;
55
56                 // parser output //
57                 int CurLoc;     // mouse cursor position in text.
58
59         public AutoMODIMainForm()
60         {
61                         InitializeComponent();
62             md = new MODI.Document();
63             FileNameQue = new Queue<string>();
64
65 #if true
66             string exepath = System.IO.Path.GetTempPath();
67             exepath += "amodi\\";
68
69                         try
70                         {
71                                 System.IO.Directory.Delete(exepath);
72                         } catch { }
73             System.IO.Directory.CreateDirectory(exepath);
74 #else
75             string exepath = Application.StartupPath;
76             lbFileName.Text = "Watching... - " + exepath;
77 #endif
78             fsw = new System.IO.FileSystemWatcher();
79             fsw.Path = exepath;
80             fsw.IncludeSubdirectories = false;
81             fsw.SynchronizingObject = this;
82             fsw.Changed += new System.IO.FileSystemEventHandler(watcher_Changed);
83             fsw.EnableRaisingEvents = true;
84         }
85         void Cleanup()
86         {
87             fsw.EnableRaisingEvents = false;
88             fsw.Dispose();
89             fsw= null;
90         }
91
92         private void btnDoOCR_Click(object sender, EventArgs e)
93         {
94             DoOCR(tbFileName.Text);
95         }
96
97         private bool DoingOCR = false;
98         bool DoOCR(string filename)
99         {
100             if (DoingOCR) return false;
101             DoingOCR = true;
102
103             bool capture_page = miCapturePage.Checked;
104
105                         ParseFileName(filename);
106
107             lbStatus.Text = "Recognizing... " + filename;
108             tbText.Text = "";
109             tbInfo.Text = "";
110             for (int i = 0; i < 10; i++){
111                 try {
112                     md.Create(filename);
113                 } catch {
114                     tbInfo.AppendText("MODI Create failure: " + filename + "\r\n");
115                     DBW("MODI Create file failure: " + filename);
116                     System.Threading.Thread.Sleep(30);
117                     continue;
118                 }
119                 break;
120             }
121             DBW("DoOCR:OCR");
122             try {
123                                 if (miUseDefLang.Checked){
124                                         md.OCR(MODI.MiLANGUAGES.miLANG_SYSDEFAULT, true, true);
125                                 } else {
126                                         md.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, true, true);
127                                 }
128             } catch {
129                 DBW("MODI OCR Error: " + filename);
130                 md.Close();
131                 DBW("DoOCR:Closed");
132                 lbStatus.Text = "OCR Error: " + filename;
133                 DoingOCR = false;
134                 return false;
135             }
136             DBW("DoOCR:Completed");
137             const int UnderGap = MARGIN_UNDER_CLICK; // 単語のある領域より少し下のpointでも検索対象と認識する空白部分(Y方向)
138             int last_x = 0;
139             int lineno = 0;
140                         CurLoc = 0;
141             lbPoint.Text = "" + CursorPoint.X + "," + CursorPoint.Y;
142             tbInfo.AppendText("Page:" + md.Images.Count + " pt:" + CursorPoint.X + "," + CursorPoint.Y + "\r\n");
143             for (int i = 0; i < md.Images.Count; i++)
144             {
145                 MODI.Image image = (MODI.Image)md.Images[i];
146                 MODI.Layout layout = image.Layout;
147                                 bool outok = capture_page;
148                                 string prevWord = "";
149                                 for (int j = 0; j < layout.Words.Count; j++)
150                 {
151                     MODI.Word word = (MODI.Word)layout.Words[j];
152                     bool cr = false;
153                     bool curLocSet = false;
154
155                     for (int k = 0; k < word.Rects.Count; k++)
156                     {
157                         MODI.MiRect rc = (MODI.MiRect)word.Rects[k];
158                         int h = rc.Bottom - rc.Top;
159                         int w = rc.Right - rc.Left;
160
161                         //bool incursor;
162                                                 //tbText.AppendText(word.Text + " (" + rc.Left + "," + rc.Top+ ")\r\n");
163                         if (CursorPoint.Y >= rc.Top && CursorPoint.Y <= rc.Bottom+UnderGap){
164                             //incursor = true;
165                                                         if (!outok)
166                                                         {
167                                 if (CursorPoint.X < rc.Left) {
168                                     // cursorを飛び越えた
169                                     outok = true;
170                                                                         curLocSet = true;
171                                     if (prevWord.Length != 0) {
172                                         tbText.AppendText(prevWord + " ");
173                                         CurLoc = prevWord.Length + 1;
174                                     }
175                                 } else
176                                                                         if (CursorPoint.X >= rc.Left && CursorPoint.X <= rc.Right){
177                                                                                 outok = true;
178                                                                                 curLocSet = true;
179                                         if (prevWord.Length != 0) {
180                                             tbText.AppendText(prevWord + " ");
181                                             CurLoc = prevWord.Length + 1;
182                                         }
183                                                                         } else {
184                                                                                 prevWord = word.Text;
185                                                                         }
186                                                         }
187                         } else {
188                             //incursor = false;
189                         }
190
191                         if (outok){
192                             tbInfo.AppendText(word.Text + " (" + w + "x" + h + ":" + rc.Left + "," + rc.Top + ")\r\n");
193                         }
194
195                         if (last_x > rc.Left){
196                             if (tbText.Text!="")
197                                 cr = true;
198                             lineno++;
199                         }
200                         last_x = rc.Left;
201                     }
202
203                     if (outok){
204                         if (cr){
205                             tbText.AppendText("\r\n");
206                             if (curLocSet)
207                                 CurLoc += 2;    // CR+LF
208                         }
209
210                         tbText.AppendText(word.Text + " ");
211                     }
212                 }
213             }
214             md.Close(false);
215             lbStatus.Text = "Done. " + filename;
216             DoingOCR = false;
217             return true;
218         }
219                 private void ParseFileName(string filename)
220                 {
221                         Regex r = new Regex(@"\((?<x>\d+),(?<y>\d+)\)");
222                         Match m = r.Match(filename);
223                         if (m.Success)
224                         {
225                                 CursorPoint.X = int.Parse(m.Groups["x"].Value);
226                                 CursorPoint.Y = int.Parse(m.Groups["y"].Value);
227                         }
228                 }
229
230         //イベントハンドラ
231         private void watcher_Changed(System.Object source,
232             System.IO.FileSystemEventArgs e)
233         {
234             switch (e.ChangeType)
235             {
236                 case System.IO.WatcherChangeTypes.Changed:
237                     string ext = System.IO.Path.GetExtension(e.FullPath);
238                     if (ext==".gif" || ext==".jpg" || ext==".png" || ext==".tif" || ext==".bmp" || ext==".dib")
239                     {
240                         PostOCR(e.FullPath);
241                     }
242                     break;
243 //                case System.IO.WatcherChangeTypes.Created:
244                     //break;
245 //                case System.IO.WatcherChangeTypes.Deleted:
246   //                  break;
247             }
248         }
249
250         private void PostOCR(string filename)
251         {
252             FileNameQue.Enqueue(filename);
253             PostMessage(this.Handle, WM_EXEC_OCR, IntPtr.Zero, IntPtr.Zero);
254         }
255
256         private void ExecOCR(string filename)
257         {
258             if (DoOCR(filename)) {
259                 string textname = filename + ".txt";
260                 for (int i = 0; i < 10; i++) {
261                     try {
262                         StreamWriter writer = new StreamWriter(textname, false, System.Text.Encoding.GetEncoding("utf-16"));
263                         writer.WriteLine(CurLoc.ToString());
264                         writer.Write(tbText.Text);
265                         writer.Close();
266                     } catch {
267                         tbInfo.AppendText("Write Error:" + textname + "\r\n");
268                         System.Threading.Thread.Sleep(30);
269                         continue;
270                     }
271                     break;
272                 }
273             }
274             if (!miDebugMode.Checked) {
275                 try {
276                     System.IO.File.Delete(filename);
277                 }
278                 catch
279                 {
280                     // 連続して.bmpファイルが作られているため
281                     tbInfo.AppendText("Delete Error:" + filename + "\r\n");
282                 }
283             }
284         }
285
286         private void miExit_Click(object sender, EventArgs e)
287         {
288             Close();
289         }
290
291         enum AMODI_CMD
292         {
293             QUERY = 0,
294             PAGE_CAPTURE = 1,
295         };
296         struct POINT
297         {
298             public int x;
299             public int y;
300         };
301         Point CursorPoint;
302         unsafe static Point int2point(IntPtr param)
303         {
304                         POINT pt = (POINT)Marshal.PtrToStructure((IntPtr)param, typeof(POINT));
305             Point p = new Point();
306             p.X = pt.x;
307             p.Y = pt.y;
308             return p;
309         }
310         // interface for external app
311         protected override void WndProc(ref Message m)
312         {
313             if (m.Msg == WM_AMODI)
314             {
315                 switch ((AMODI_CMD)m.WParam)
316                 {
317                     case AMODI_CMD.QUERY:
318                         m.Result = (IntPtr)m.LParam;
319                         return;
320                     case AMODI_CMD.PAGE_CAPTURE:
321                         m.Result = (IntPtr)(miCapturePage.Checked ? 1 : 0);
322                         return;
323                     default:
324                         break;
325                 }
326             } else
327             if (m.Msg == WM_EXEC_OCR) {
328                 string filename = "";
329                 while (FileNameQue.Count()!=0) {
330                     filename = FileNameQue.Dequeue();
331                 }
332                 if (filename != "") {
333                     ExecOCR(filename);
334                 }
335             } else
336             if (m.Msg == WM_COPYDATA)
337             {
338                 COPYDATASTRUCT cds = new COPYDATASTRUCT();
339                 cds = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
340                 if (cds.dwData == (IntPtr)WMCD_EXISTCHECK)
341                 {
342                     m.Result = (IntPtr)1;
343                     return;
344                 } else
345                                 if (cds.dwData == (IntPtr)WMCD_SETPOINT){
346                                         CursorPoint = int2point(cds.lpData);
347                                         Console.WriteLine("Cursor:" + CursorPoint.X + "," + CursorPoint.Y);
348                                         return;
349                                 } else
350                                 if (cds.dwData == (IntPtr)WMCD_RESTORE_WINDOW)
351                                 {
352                                         this.Show();
353                                 }
354 #if false   // 参考
355                 if (cds.cbData > 0)
356                 {
357                     byte[] data = new byte[cds.cbData];
358                     Marshal.Copy(cds.lpData, data, 0, cds.cbData);
359                     //あとは data に COPYDATA の内容が入ってるので適宜処理
360                 }
361                 m.Result = (IntPtr)1;
362 #endif
363             }
364             base.WndProc(ref m);
365         }
366
367         private void miCapturePage_Click(object sender, EventArgs e)
368         {
369             miCapturePage.Checked = !miCapturePage.Checked;
370         }
371
372                 private void AutoMODIMainForm_Activated(object sender, EventArgs e)
373                 {
374                         //this.Hide();
375                 }
376
377                 private void miDebugMode_Click(object sender, EventArgs e)
378                 {
379                         miDebugMode.Checked = !miDebugMode.Checked;
380                 }
381
382                 private void miUseDefLang_Click(object sender, EventArgs e)
383                 {
384                         miUseDefLang.Checked = !miUseDefLang.Checked;
385                 }
386
387         static int hWin = 0;
388         void DBW( string msg )
389         {
390                 if ( hWin==0 ){
391                         hWin = FindWindow( "TDbgMsgForm", "Debug Messenger" );
392                         if ( hWin==0 ) return;
393                 }
394             byte[] bytearray = System.Text.Encoding.Default.GetBytes(msg);
395             int len = bytearray.Length;
396                 COPYDATASTRUCT_send cds;
397                 cds.dwData = 1; // Indicate String
398                 cds.cbData = len + 1;
399             cds.lpData = msg;
400                 SendMessage( (IntPtr)hWin, WM_COPYDATA, IntPtr.Zero, ref cds );
401         }
402     }
403 }