Evernoteへメモを追加する。(添付ファイル付)
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
| 固定リンク
