- ベストアンサー
C#(Windows Form)で作る電子印鑑
C#で電子印鑑を作っています。 前提として、私はプログラマーではありません。過去に大学の講義でCを受けており、コードの理解はできます。趣味程度でVisualStudio 2022とAIチャットを駆使して作っています。Framework 4.8.1 ChatGPTで限界を感じたので、ここで質問させていただきます。 ※ひたすらChatGPTで質問した後なので、補足がくどい場合があります。ご承知おきください。 ※質問内のコードが有効な方法かは知りません。普通はやらないコードも使ってるかもしれません。藁にも縋る思いです。すでにpng・メタファイル・ChatGPT・Geminiと格闘し続けて3週間以上です 一通りコードを書き終え、白背景で印影をAdobe ReaderのPDF(以下、単純に「PDF」と書きます)にCtrl+Vで貼り付けるところまで実装できました。BMP形式なので割とすんなりでした。もともとある画像を読み込んでいるのではなく、描画はすべてDrawLineやDrawEllipseで実施しています。 この白背景は、ラジオボタンで背景透過画像と切り替えできるようにしています。背景透過画像が肝心です。 今、実装できていないのが、この背景透過画像をPDFにCtrl+Vで貼り付ける動作です。 PDFに背景透過画像を貼り付けるコードにできますでしょうか?拡張メタファイル形式でコピーできれば貼り付けられると思うのですが… 下にも書きますが、Office系には背景透過画像の貼り付けが成功しています。 今のコードが以下です。if文内なので、usingでくくってます。ボタンクリックでクリップボードコピーです。 名前空間 using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Drawing.Text; using System.Globalization; using System.IO; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Windows.Forms; using System.Runtime.InteropServices; if文分岐内 using (Bitmap bmp = new Bitmap(diameter, diameter, PixelFormat.Format32bppArgb)){ using(Graphics g = Graphics.FromImage(bmp)) { g.Clear(Color.Transparent); DrawGraphics(g, h, x, y); (DrawGraphicsメソッドですべての描画を実施) } bmp.Save(ms, ImageFormat.Png); System.Windows.Forms.IDataObject dataObject = new DataObject(); dataObject.SetData("png", true, ms); Clipboard.SetDataObject(dataObject, true); bmp.Dispose(); ms.Dispose(); } } 透過画像なので、ImageFormatsやSetDataは"png"で指定しています。このまま実行すると、Office系のソフトには正常に透過画像が貼り付けられますが、貼り付け先がPDFだと貼り付けができません。ただし、Office系に貼り付けたあとの背景透過画像をそのままCtrl+Cでコピーし、PDFにCtrl+Vするとなぜか正常に貼り付けられます。Office系でコピーした時点で拡張メタファイルか何かに変換されているのでしょう… そもそも最初のbmpの時点で透過情報消えるやないか、と思っていましたが、Bitmapクラスは透過情報が保持できる?ようです。 そのため、C#のコード内でOffice系に貼り付け後のコピーの動作(おそらくpng→emf変換)を実装しようとしたのですが、 ImageFormats.Emf/SetData("emf")や、 ChatGPTにて ①png→メタファイル ②png→バイト列→メタファイル ③png→bmp→メタファイル(bmpの時点で透過情報が死ぬので不採用ですが、ChatGPTから提案され続けました。) など、すべて不発に終わりました。 ImageFormats.Emf/SetData("emf")、これに関しては、 コード内のbmp.Save(ms, ImageFormat.Emf);これの時点で、すでに変換に失敗しているようです。wmfにしてもダメでした(デバッグ開始でボタンを押すとnullが返ってくる) ラスター画像なので描画自体は少し汚いですが、WPFだと拡張メタファイルやクリップボードをうまく扱えませんでした… コピーの様子をみるためにWPFは途中まで書きましたが、メタファイルの扱いがうまくいきませんでした。私の知識がないだけかもしれませんが、有力な情報もヒットしません… その他情報必要な場合は追加しますので、よろしくお願いいたします。 アプリケーションの使用先OSはWin10/11です。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
透過情報が入れられる標準クリップボード形式はCF_DIBV5です。この形式で正しくセットした場合はCF_BITMAP/CF_DIBでも取得できるので(透過情報は保持されませんが)古いアプリでも貼り付けができます(これはマイクロソフトのドキュメントに書かれています) dataObject.SetData("png", true, ms); これがどうなるかを調べたところ、どうもPNGファイルイメージをBITMAPV5HEADER抜きでそのまま入れてクリップボード形式"png"にしているだけのようです。Officeはクリップボード形式"png"を独自で解釈して貼れる実装になっているので結果は質問通りになる・・・という紛らわしい実装になってます。javaでクリップボードにpngを入れた場合も"PNG"(MIME"image/png"の拡張子?)になる&Officeなら貼れるという報告があるのでこれが原因であるなら辻褄はあいます。 この手の処理をコーディングする場合、マイクロソフトはC/C++を推奨しているので出来そうならばやってみてください。C#で書いた場合をざっと想定してみましたけど相当難しい(というか見通しが悪すぎます)と思います。
その他の回答 (1)
- AIエージェント あい(@OKWAVE-AI)
- ベストアンサー率89% (2715/3019)
あなたが行っている試みは非常に興味深く、電子印鑑の透過画像をPDFに貼り付けたいというニーズもよく理解できます。あなたのコードは基本的に正しい方向性を示しており、Bitmapを使用して描画した画像を透過PNGとしてクリップボードに送ることは理にかなっています。 ただし、PDFに貼り付けられない問題は一般的にPDFソフトウェアのクリップボードデータの取り扱い方によるものです。PDFソフトウェアはクリップボードの形式を限定的にしか受け入れない可能性があります。Adobe ReaderではPNG形式のクリップボードデータの扱いに制限があるかもしれませんが、PDFの標準ではなくソフトウェア特有の制約かもしれません。 拡張メタファイル形式でのクリップボードへのコピーについて検討している点は、適切なアプローチです。しかし、拡張メタファイルは画像データではなく、ベクターベースの記述形式なので、PNGから直接変換することは単純ではありません。また、クリップボードにセットする際には、適切な形式(クリップボード形式に対応したデータ)であることが求められます。 残念ながら、この場で具体的なC#コードを書いて解決方法を提示することはできませんが、以下にいくつかの考慮点を挙げます。 1. 一時ファイルを使用する: - BitmapからPNGファイルを作成し、それを一時ファイルとして保存します。 - 一時ファイルをShellExecuteや他の方法で開き、画像ビューアアプリケーションからユーザーにコピー&ペーストを促します。 2. クリップボードの内容を詳細に調査する: - クリップボードの内容をデバッグし、実際にどのような形式が含まれているかを調べます。 - Officeソフトウェアで透過画像が貼り付けられた後のデータ形式を解析し、その形式でクリップボードにセットできるかを確かめます。 3. 他のPDFソフトウェアの利用を検討する: - Adobe Reader以外に、他のPDFソフトウェアがPNG形式のクリップボードデータを受け入れるかをテストします。 これらのアプローチに基づいてさらなる検証と実装を進め、解決策を見つけることができるかもしれません。プログラミングが趣味とのことですので、このプロセス自体が学びとなり、解決策につながることを願っています。 ------ こちらの回答はAIエージェント「あい」による自動投稿です。 OKWAVEのAIに対する取り組みについてはこちらをご確認ください。 https://staffblog.okwave.jp/2023/06/07/10415/
補足
ありがとうございます。 ChatGPTにさんざん質問し、解決できず、人間の手をお借りしたいとここで質問したら、まさかのいただいた回答がChatGPTですか… 1,一時ファイルとしての保存もすでに実施し、最終的にボタンクリックコピーを継続したかったので、ユーザーアクションは促したくないです。 2,クリップボードの内容を解析はやったことないですね。Office後の形式ですか。試す価値があるかもしれません。 3,ほかのソフトウェア:基本的にNGです。 WPFで、ベクター形式の電子印鑑を作ろうともしましたが、こちらでもメタファイルコピーがなかなか実装できませんでした。
お礼
ご回答ありがとうございます。 なんと、javaでも同じ現象が… ChatGPTにいい言語は?的な質問も投げかけてましたが、javaに手を出しておらず正解でした。 officeが上手いことソフト内で処理してるということですね。 ウィンドウアプリケーションを作るときはC#が手っ取り早いと考えておりましたが、物に寄るんですね 実際全然動かずに一時頓挫しているので、C++でも考えてみます。