【BBB】 1回目 Kindleを画像保存するソフトを作ってみた 2023年2月12日14時07分
Kindleを画像保存するソフトを開発してみました。
ほとんど、需要はかいかと思いますが。
Kindleの横サイズに、Windowを合わせる。
※Manualにチェックを入れると、上下方向も合わせることが可能。
ひだりめくり、みぎめくりをチェックする。
Startボタンを押す。
これだけで、全ページ、自動で保存されます。
using System.Diagnostics;
using System.Windows.Automation;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace KindleApp
{
public partial class Form1 : Form
{
int ii = 0;
string kindleName = String.Empty;
string taiheyo = "根拠地データ";
string turnP = "Turn Page";
int pageLR = 0;
int capTop = 0;
int capLeft = 0;
int capWidth = 0;
int capHeight = 0;
InvokePattern btnClear;
Process pp;
private static AutomationElement mainForm;
[StructLayout(LayoutKind.Sequential)]
private struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
private const int DWMWA_EXTENDED_FRAME_BOUNDS = 9;
[DllImport("user32.dll")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
extern static IntPtr GetForegroundWindow();
[DllImport("dwmapi.dll")]
extern static int DwmGetWindowAttribute(IntPtr hWnd, int dwAttribute, out Rect rect, int cbAttribute);
// 指定したName属性に一致するAutomationElementをすべて返します
private static IEnumerable<AutomationElement> FindElementsByName(AutomationElement rootElement, string name)
{
return rootElement.FindAll(
TreeScope.Element | TreeScope.Descendants,
new PropertyCondition(AutomationElement.NameProperty, name))
.Cast<AutomationElement>();
}
public Form1()
{
InitializeComponent();
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
if (radioButton1.Checked) pageLR = 0;
}
private void radioButton2_CheckedChanged(object sender, EventArgs e)
{
if (radioButton2.Checked) pageLR = 1;
}
private void button4_Click(object sender, EventArgs e)
{
Rect bounds;//, rect;
// アクティブウィンドウを取得
IntPtr hWnd = GetForegroundWindow();
IntPtr winDC = GetWindowDC(hWnd);
DwmGetWindowAttribute(hWnd, DWMWA_EXTENDED_FRAME_BOUNDS, out bounds, Marshal.SizeOf(typeof(Rect)));
int ww = bounds.right - bounds.left;
int hh = bounds.bottom - bounds.top;
capWidth = ww;
if (chkM.Checked)
{
capHeight = hh;
capTop = this.Top;
}
else
{
capHeight = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;// hh;
capTop = 0;// this.Top;
}
capLeft = this.Left;
this.Width = 233;
this.Height = 141;
this.Top = 0;
this.Left = 0;
button8.Enabled = true;
}
private void bgWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
// このメソッドへのパラメータ
int bgWorkerArg = (int)e.Argument;
// senderの値はbgWorkerの値と同じ
BackgroundWorker worker = (BackgroundWorker)sender;
// 時間のかかる処理
while (true)
{
// キャンセルされてないか定期的にチェック
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
ii++;
btnClear.Invoke();
if (capcap(ii)) break;
System.Threading.Thread.Sleep(200);
int percentage = ii;// * 100 / bgWorkerArg; // 進ちょく率
worker.ReportProgress(percentage);
}
// このメソッドからの戻り値
e.Result = "すべて完了";
}
private void bgWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
}
private void bgWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("キャンセルされました");
// この場合にはe.Resultにはアクセスできない
}
else
{
// 処理結果の表示
this.Text = e.Result.ToString();
MessageBox.Show("正常に完了");
if (MessageBox.Show("正常に完了", "継続?", MessageBoxButtons.YesNo)==DialogResult.Yes)
{
// retry
string oldFile = "C:\\temp\\book\\test\\" + "Old.png";
string latestFile = "C:\\temp\\book\\test\\" + "Latest.png";
System.IO.File.Delete(oldFile);
System.IO.File.Delete(latestFile);
bgWorker.RunWorkerAsync(60);
}
}
button9.Enabled = false;
button8.Enabled = true;
}
private bool capcap(int page)
{
// アクティブウィンドウを取得
IntPtr hWnd = GetForegroundWindow();
//IntPtr winDC = GetWindowDC(hWnd);
// 画像のサイズを指定し、Bitmapオブジェクトのインスタンスを作成
Bitmap bm = new Bitmap(capWidth, capHeight);
// Graphicsオブジェクトのインスタンスを作成
Graphics gr = Graphics.FromImage(bm);
// 画面全体をコピー
gr.CopyFromScreen(new Point(capLeft, capTop), new Point(0, 0), bm.Size);
// PNGで保存
string p = page.ToString().PadLeft(4, '0');
string oldFile = "C:\\temp\\book\\test\\" + "Old.png";
string latestFile = "C:\\temp\\book\\test\\" + "Latest.png";
if (System.IO.File.Exists(latestFile))
{
System.IO.File.Delete(oldFile);
System.IO.File.Move(latestFile, oldFile);
}
bm.Save(latestFile, System.Drawing.Imaging.ImageFormat.Png);
gr.Dispose();
if (System.IO.File.Exists(oldFile))
{
if (ContentsEqual(oldFile, latestFile))
{
return true;
}
}
bm.Save("C:\\temp\\book\\test\\" + p + ".png", System.Drawing.Imaging.ImageFormat.Png);
return false;
}
public static bool ContentsEqual(string path1, string path2)
{
if (path1 == path2)
{
return true;
}
FileStream fs1 = null;
FileStream fs2 = null;
try
{
fs1 = new FileStream(path1, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
fs2 = new FileStream(path2, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
if (fs1.Length != fs2.Length)
{
return false;
}
int file1byte;
int file2byte;
do
{
file1byte = fs1.ReadByte();
file2byte = fs2.ReadByte();
}
while ((file1byte == file2byte) && (file1byte != -1));
return (file1byte - file2byte) == 0;
}
finally
{
using (fs1)
{ }
using (fs2)
{ }
}
}
private void button8_Click(object sender, EventArgs e)
{
button8.Enabled = false;
kindleName = textBox1.Text;
if (!Directory.Exists(@"C:\temp\book\test")) Directory.CreateDirectory(@"C:\temp\book\test");
ii = 0;
bool hit = false;
foreach (var p in Process.GetProcesses())
{
if (p.MainWindowTitle.Contains(kindleName))
{
pp = p;
hit = true;
break;
}
}
if (!hit) return;
mainForm = AutomationElement.FromHandle(pp.MainWindowHandle);
try
{
if (pageLR == 0)
{
btnClear = FindElementsByName(mainForm, "Turn Page").First()
.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
}
else
{
btnClear = FindElementsByName(mainForm, "Turn Page").Last()
.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
}
}
catch (Exception ex)
{
string ss = ex.Message;
}
button9.Enabled = true;
// 時間のかかる処理を別スレッドで開始
bgWorker.RunWorkerAsync(60);
}
private void button9_Click(object sender, EventArgs e)
{
bgWorker.CancelAsync();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Opacity = 0.8;
this.Text = "KindleUnlimitedReal";
}
}
}
こんな感じです。
この記事が気に入ったらサポートをしてみませんか?