Evernoteへメモを追加する。(添付ファイル付)
今回は、添付ファイルと共にメモを追加してみます。前回のソースにListView1, ImageList1, Splitter1を追加します。添付ファイルは、ExplorerからのDrag&Dropで取得します。ExplorerからのターゲットをMemo1としているため、Mr.XRAYさんところのSubClassコンポーネントを使わせて頂いています。(フォームをターゲットとして、WM_DROPFILESで処理するとサブクラスは必要はないです。)
実行するとこんな感じ
Evernoteではこんな感じ
サブクラス用コンポーネント
Delphi Library [Mr.XRAY]
SubClassUnit
http://homepage2.nifty.com/Mr_XRAY/Halbow/Notes/N004.html
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.ToolWin, Vcl.ComCtrls, Vcl.ImgList, SubClassUnit; type TForm1 = class(TForm) Memo1: TMemo; Panel1: TPanel; Title: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Edit1: TEdit; Edit2: TEdit; Edit3: TEdit; Edit4: TEdit; Button1: TButton; Button2: TButton; ListView1: TListView; Splitter1: TSplitter; ImageList1: TImageList; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); private SubClass1: TSubClass; procedure SubClass1MessageAfter(Sender: TObject; var Message: TMessage); procedure DropFiles(H: THandle); procedure MakeTempFile(FileName: String); public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} uses ShellAPI, EncdDecd, // BASE64 Encording IdHashMessageDigest; // MD5値 const Temp = 'Evernote.enex'; S1 = '<?xml version="1.0" encoding="UTF-8"?>'+ '<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export.dtd">'+ '<en-export>'; // エクスポートしたファイルには、その時の日時や // EverNoteのバージョンが入っていますが、 // なくても動作しましたので、消しました。 // 複数ある場合は、<note></note>までを繰り返す。 S2 = '<note>'; // ここにタイトル <title>タイトル</title> S3 = '<content>' + '<![CDATA[' + '<?xml version="1.0" encoding="UTF-8"?>' + '<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">'+ '<en-note style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">'; // ここに本文・添付ファイル // e.g.) // 1行目文字-ファイル1-2行目文字-ファイル2、ファイル3-3行目文字の場合 // <div>1行目文字</div> // <en-media hash="ファイル1のMD5値" style="cursor: default; vertical-align: middle;" type="application/octet-stream"/> // <div>2行目文字</div> // <div> // <en-media hash="ファイル2のMD5値" style="cursor: default; vertical-align: middle;" type="application/octet-stream"/> // <en-media hash="ファイル3のMD5値" style="cursor: default; vertical-align: middle;" type="application/octet-stream"/> // <div>3行目文字</div> // </div> F1 = '<en-media hash='; F2 = ' style="cursor: default; vertical-align: middle;" type="application/octet-stream"/>'; S4 = '</en-note>' + ']]>' + '</content>'; // ここに作成日時 <created>20111001T042516Z</created> // ここにタグ <tag>タグ1</tag> <tag>タグ2</tag> S5 = '<note-attributes>'; // ここにURL <source-url>http://delphi-fan</source-url> S6 = '</note-attributes>'; // ここに添付ファイル本体 - 複数ある場合は、<resource></resource>の繰り返し // <resource><data encoding="base64"> // ファイルデータ(BASE64でエンコード) // </data> // <mime>application/octet-stream</mime> // <resource-attributes> // <source-url>file://ファイル名(パス付)</source-url> // <file-name>ファイル名(パス無)</file-name> // </resource-attributes> // </resource> F3 = '<resource><data encoding="base64">'; // ここにデータ F4 = '</data>'; F5 = '<mime>application/octet-stream</mime>'; F6 = '<resource-attributes>'; F7 = '<source-url>file://'; // ここにファイル名(パス付) F8 = '</source-url>'; F9 = '<file-name>'; // ここにファイル名(パス無) F10 = '</file-name>'; F11 = '</resource-attributes>'; F12 = '</resource>'; S7 = '</note>'; S8 = '</en-export>'; // Evernoteエクスポートファイル (ENEX)の作成 procedure TForm1.MakeTempFile(FileName: String); // UTCの日時-「年月日T時分秒Z」という文字列にします。 function GetCreateDateTime: String; var UTC: TSystemTime; begin GetSystemTime(UTC); with UTC do Result := Format('%.2d%.2d%.2dT%.2d%.2d%.2dZ', [wYear,wMonth,wDay,wHour,wMinute,wSecond]); end; // ファイルをBASE64文字列で返します。 function GetBody(const FileName: String): String; var MS: TMemoryStream; begin MS := TMemoryStream.Create; try MS.LoadFromFile(FileName); Result := EncodeBase64(MS.Memory, MS.Size); finally MS.Free; end; end; // ファイルのMD5値を取得します。 function GetMD5(const FileName : String) : String; var idHMD5 : TIdHashMessageDigest5; FS : TFileStream; begin idHMD5 := TIdHashMessageDigest5.Create; FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try // Evernoteエクスポートファイル (ENEX)では小文字が使われています。 // 大文字のままで動作しましたが、一応元ファイルに合わせています。 Result := AnsiLowerCase(idHMD5.HashStreamAsHex(FS)); finally FS.Free; idHMD5.Free; end; end; var SL1, SL2: TStringList; I: Integer; S: String; begin SL1 := TStringList.Create; SL2 := TStringList.Create; try SL2.Delimiter := ','; SL2.StrictDelimiter := True; SL1.Add(S1); SL1.Add(S2); // タイトル SL1.Add('<title>'+Edit1.Text+'</title>'); SL1.Add(S3); // 本文 1行目から<div></div>でいいみたい for I := 0 to Memo1.Lines.Count -1 do SL1.Add('<div>'+Memo1.Lines[I]+'</div>'); // 添付ファイル - このサンプルでは、本文の最後にまとめて追加します。 for I := 0 to ListView1.Items.Count -1 do begin S := ListView1.Items[I].SubItems[0]; // ファイル名 SL1.Add(F1+'"'+GetMD5(S)+'"'+F2); // MD5 end; SL1.Add(S4); // 作成日時 SL1.Add('<created>'+GetCreateDateTime+'</created>'); // タグ SL2.CommaText := Edit2.Text; for I := 0 to SL2.Count -1 do SL1.Add('<tag>'+SL2[I]+'</tag>'); SL1.Add(S5); // URL if Trim(Edit3.Text) <> '' then SL1.Add('<source-url>' + Edit3.Text + '</source-url>'); SL1.Add(S6); // ファイルデータ for I := 0 to ListView1.Items.Count -1 do begin S := ListView1.Items[I].SubItems[0]; // ファイル名 SL1.Add(F3+GetBody(S)+F4+F5+F6); // ファイルデータ SL1.Add(F7+S+F8); SL1.Add(F9+ExtractFileName(S)+F10+F11+F12); end; SL1.Add(S7); SL1.Add(S8); SL1.SaveToFile(FileName, TEncoding.UTF8); Sleep(50); // おまじない finally SL2.Free; SL1.Free; end; end; // ファイルを作成してEvernoteに読み込ませます。 procedure TForm1.Button1Click(Sender: TObject); var FileName: String; Param1, Param2: String; begin FileName := ExtractFilePath(Application.ExeName) + Temp; MakeTempFile(FileName); if FileExists(FileName) then begin Param1 := 'C:\Program Files\Evernote\Evernote\ENScript'; Param2 := 'importNotes /s ' + FileName + ' /n ' + Edit4.Text; ShellExecute(Handle, 'OPEN', PWideChar(Param1), PWideChar(Param2), nil, SW_HIDE); end; end; // 同期 procedure TForm1.Button2Click(Sender: TObject); var Param1, Param2: String; begin Param1 := 'C:\Program Files\Evernote\Evernote\ENScript'; Param2 := 'syncDatabase'; ShellExecute(Handle, 'OPEN', PWideChar(Param1), PWideChar(Param2), nil, SW_HIDE); end; // 添付ファイルは、ExplorerからのDrag&Dropにて取得します。 procedure TForm1.FormCreate(Sender: TObject); begin //ListView1. // サブクラスの設定 SubClass1:= TSubClass.Create(Self); SubClass1.TargetControl := Memo1; SubClass1.OnMessageAfter := SubClass1MessageAfter; DragAcceptFiles(Memo1.Handle, True); end; procedure TForm1.SubClass1MessageAfter(Sender: TObject; var Message: TMessage); begin case Message.Msg of WM_DROPFILES: DropFiles(Message.WParam); end; end; // 添付ファイル procedure TForm1.DropFiles(H: THandle); // ファイルに関連付けられたアイコンを取出し、ImageListに追加します。 function GetIconToImageList(FileName: String): Integer; var Icon : TIcon; SHFileInfo: TSHFileInfo; begin Icon:= TIcon.Create; try SHGetFileInfo(PChar(FileName), 0, SHFileInfo, SizeOf(SHFileInfo), SHGFI_SMALLICON or SHGFI_ICON); Icon.Handle := SHFileInfo.hIcon; Result := ImageList1.AddIcon(Icon); finally Icon.Free; end; end; // 実行ファイル、リンクファイルとフォルダは、添付ファイルにしない。 function IsCorrectFileAsAttachment(FileName: String): Boolean; var S: String; begin S := UpperCase(ExtractFileExt(FileName)); Result := (S <> '.LNK') or (S <> '.EXE') or (not FileExists(FileName)); end; var I, Count: Integer; FileName: array [0..255] of Char; Files: TStringList; S: String; LI: TListItem; begin Files := TStringList.Create; try // ドロップされたファイルの取得 Count := DragQueryFile(H, Cardinal(-1), nil, 0); for I:=0 to Count-1 do begin DragQueryFile(H, I, FileName, SizeOf(FileName)-1); Files.Add(FileName); end; DragFinish(H); // ListViewに追加します。 for I := 0 to Files.Count - 1 do begin S := Files[I]; if IsCorrectFileAsAttachment(S) then begin LI := ListView1.Items.Add; LI.Caption := ExtractFileName(S); LI.SubItems.Add(S); LI.ImageIndex := GetIconToImageList(S); end; end; finally Files.Free; end; end; end.
実行するとこんな感じ
Evernoteではこんな感じ
サブクラス用コンポーネント
Delphi Library [Mr.XRAY]
SubClassUnit
http://homepage2.nifty.com/Mr_XRAY/Halbow/Notes/N004.html
| 固定リンク