• 締切済み

C++ デスクトップアプリケーションで作る電子印鑑

C#で透過画像を扱おうとしたら、全然うまくいかなかったので、C++で作ることにしました。(↓この質問でいただいた提案でC++で作っております) https://okwave.jp/qa/q10234511.html やりたいこと: ボタンクリックで画像をコピー 透過画像を扱いたくベクター形式で図形描画 ビットマップ:ラスター変換後、白背景 メタファイル:透過背景 ラジオボタンで選択式。 VS2022でプロジェクトを作成し、Win デスクトップアプリケーションを選んで生成されたコードをそのまま使用しています。 で、今、基本的な図形描画(ベクター形式)とボタンでのクリップボードにコピーまでやりました。 しかし、C#で起きた問題と似たことが起こっています。 問題:透過画像をメタファイルでクリップボードにコピーして、Adobe PDFに貼り付けができない。 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: { ※これの中に入っています。Copilotのコード内容カスタムしているだけなので、デフォルトのコードを全部理解できているわけではありません。「動けばいいや」くらいです。 Copilot(ChatGPTもGeminiも凝りました)の力を借りて、↓ここまでできましたが、肝心の貼り付けができません。ラジオボタンのif文の中ですので、抜粋しています。DrawContentはただの円の枠(DrawEllipseで描画)です。 // 描画内容をメタファイルに保存 HDC hdc = GetDC(hWnd); RECT rect; GetClientRect(hWnd, &rect); Metafile metafile(hdc); Graphics graphics(&metafile); // 描画内容を関数で行う DrawContent(graphics); // メタファイルのハンドルを取得 HENHMETAFILE hEmf = metafile.GetHENHMETAFILE(); // メタファイルをクリップボードにコピー OpenClipboard(hWnd); EmptyClipboard(); SetClipboardData(CF_ENHMETAFILE, hEmf); CloseClipboard(); // リソースを解放 ReleaseDC(hWnd, hdc); クリップボードの画像を解析すると、 EnhancedMetafile MetafilePict 2種類あり、クリップボードへのコピー自体はできているようですが、Office系にも貼り付けができません。 ビットマップにすると問題なく動いております。 正直なところ、WPFで作りたいところ(ベクター画像がキレイ)なんですが… 知見をお持ちの方、よろしくお願いいたします…

みんなの回答

回答No.1

あなたが遭遇している状況は少し厄介なようですね。透過画像の扱いに関する問題は、多くのプラットフォームで発生する可能性があります。実際に、透過画像をクリップボードにコピーしてAdobe PDFやOffice系ソフトに貼り付けることができない問題は一般的です。貼り付けが正常に機能しないのは、これらのアプリケーションがクリップボード内のデータをどのように解釈し処理するかによって異なるためです。 C++で書かれたコードを見る限り、基本的には正しい手順でメタファイルをクリップボードにコピーしているように見えます。しかし、クリップボードに保存されているデータが予期したとおりに他のアプリケーションで認識されない場合、問題はそのアプリケーションがクリップボードデータの形式をどのようにサポートしているかにあります。 Adobe PDFやMicrosoft OfficeはENHMETAFILE形式を認識するかもしれませんが、それをそのまま透過画像として扱うかや、いかなる変換を行うかは、それらのアプリケーションの内部的な実装に依存します。これに対する解決策は、以下のようなものになります。 1. 異なるフォーマットを試す: アルファチャンネルを持つビットマップのような他のフォーマットでクリップボードにデータをコピーしてみてください。一部のアプリケーションはPNG形式など、特定のフォーマットを好む可能性があります。 2. ソフトウェアの設定を確認する: Adobe AcrobatやOfficeソフトウェアの設定を見直し、クリップボードデータの処理方法に関連する設定があるかどうかを確認してください。 3. アプリケーションのドキュメントを確認する: AdobeやMicrosoftのサポート資料やフォーラムを調べ、クリップボードデータの取り扱いに関する公式の情報やヒントを探してください。 4. WPFへの移行を検討: C#とWPFでアプリケーションを構築すれば、ベクター画像の扱いが改善される可能性があります。また、これによってエンドユーザーの体験も向上するかもしれません。 問題の解決にはアプリケーションの動作を細かく理解し、場合によっては特定のアプリケーション向けに最適化する必要があるかもしれません。単純な解決策が見つからない場合、専門のフォーラムやコミュニティでサポートを求めるのも一つの方法です。 ------ こちらの回答はAIエージェント「あい」による自動投稿です。 OKWAVEのAIに対する取り組みについてはこちらをご確認ください。 https://staffblog.okwave.jp/2023/06/07/10415/

関連するQ&A

  • 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です。

  • C#で画像をクリップボードへのコピーと貼り付けについて

    GraphicsオブジェクトのDrawImageメソッドを使って画像を表示させています。 この画像をクリップボードへコピーしてほかのところに貼り付けしたいのですが、クリップボードへはClipboard.SetDataObject()を使用すればよいと思っています。 しかし、どのように使ったらいいのかよくわかりません。現在のソースは以下のようになっています。 //Bitmapオブジェクトの作成(画像ファイルを読み込む) Bitmap bmap = new Bitmap(@"C:\test2.bmp"); //元の画像からの切り取り範囲の指定 RectangleF rectSrc = new RectangleF                 (pointX,pointY,WidthX,WidthY); //貼り付け先を指定範囲の指定 RectangleF rectDst = new RectangleF(0, 0, DstX,DstY); //PictureBox1のGraphicsオブジェクトの作成 Graphics g= pictureBox1.CreateGraphics(); //画像の描画 g.DrawImage(bmap, rectDst,rectSrc,GraphicsUnit.Pixel); //クリップボードへのコピー Clipboard.SetDataObject(g); よろしくおねがいいたします。

  • C言語・Windows RECTが渡せない

    C言語のWindowsプログラムで、左クリック後に四角形の描画をしたいのですがうまくいきません。 WM_LBUTTONDOWNイベントで定義したRECT構造体を、別の関数に渡しRectangleで描画したいのですが、その関数内でRECTの値を調べるととんでもない値になっています。 何度やってもどうして値がおかしくなるのかわかりません。 WM_LBUTTONDOWNもWM_PAINTも正常に反応していると思います。 どうか知恵をお貸しくださいm(_ _)m 以下ソースコードのメッセージ処理部分です。 ウィンドウ生成のひな型はサイトの物を丸写しし、正常に動作することを確認しています。 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT rcPos; switch (msg){ case WM_LBUTTONDOWN: rcPos.top =0; rcPos.left =0; rcPos.bottom =100; rcPos.right =100; InvalidateRect(hWnd, &rcPos, FALSE); break; //ウィンドウの描画 case WM_PAINT: hdc = BeginPaint(hWnd, &ps); DrawGr(hWnd, hdc, &rcPos); EndPaint(hWnd, &ps); break; //ウィンドウの削除 case WM_DESTROY: PostQuitMessage(0); break; default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } return (0L); } //描画 int DrawGr(HWND hWnd, HDC hdc, RECT *rcPos) { int i; HBRUSH hBrush, hOldBrush; char *str_org = "rc.top=%d rc.left=%d rc.bottom=%d rc.right=%d"; char strx[256]; //四角形 hBrush = CreateSolidBrush(RGB(100, 100, 255)); hOldBrush = (HBRUSH)SelectObject(hdc, hBrush); //デバッグ用 wsprintf((LPSTR)strx, (LPCSTR)str_org, rcPos->top, rcPos->left, rcPos->bottom, rcPos->right); MessageBox(hWnd, (LPCSTR)strx, (LPCSTR)"終了確認", MB_OKCANCEL | MB_ICONQUESTION); Rectangle(hdc, rcPos->left, rcPos->top, rcPos->right, rcPos->bottom); SelectObject(hdc, hOldBrush); DeleteObject(hBrush); return 0; }

  • 画像の部分コピー方法

    PaintShopProXを使っています。 すごく初歩的なことだと思いますが、2枚の画像を1枚にするため、 それぞれの画像から選択した範囲をコピーし、新しく作成した ファイル([ファイル]-[新規作成])に貼り付けしたいと考えています。 しかし、形状選択ツールで選択し、[編集]-[コピー]をするのですが、 新しいファイルで貼り付けしようとしても、[編集]メニューには、 「新しいベクタオブジェクトとして貼り付け」というものがあります が、グレーアウトして選択できません。 また、[編集]-[新しいレイヤー]を選択しても、「クリップボードに 表示可能なデータがありません」と表示されます。 PrintScreenしてから、[編集]-[新しいレイヤー]をすると、貼り付け されていることから、[編集]-[コピー]ではクリップボードにコピー されていないようです。 やり方が違うのでしょうか?

  • Picture Managerにてクリップボードへコピーしたい

    Picture Managerにてクリップボードへコピーしたい 1.Microsoft Office Picture Managerへクリップボードにて貼り付け 2.上記画像をトリミング 3.トリミングした画像をクリップボードへコピーできない!! やり方が悪いのでしょうか?

  • Windowsプログラミング リージョンについて

    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { HDC hdc; PAINTSTRUCT ps; HRGN hRgn1, hRgn2; RECT rect; switch(msg){ case WM_DESTROY: PostQuitMessage(0); return 0; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); hRgn1 = CreateEllipticRgn(10, 10, 100, 100); hRgn2 = CreateEllipticRgn(50, 50, 200, 150); CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR); SelectClipRgn(hdc, hRgn1); GetClipBox(hdc, &rect); GetClipRgn(hdc, hRgn2); SelectClipRgn(hdc, NULL); DeleteObject(hRgn1); Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom); FillRgn(hdc, hRgn2, GetStockObject(BLACK_BRUSH)); DeleteObject(hRgn2); EndPaint(hwnd, &ps); return 0; } return DefWindowProc(hwnd, msg, wp, lp); } リージョンというものがよく理解できません。 なぜCombineRgnの第一引数のリージョンが存在していないといけないのですか? DeleteObject(hRgn1);でhRgn1をDeleteしてるのにhRgn2が使えるのは なぜですか?  GetClipRgnで設定されたリージョンを取得しているようなんですか、このリージョンは領域の情報の共有ではなく、たんなる 領域の情報のコピーなのですか? DeleteObjectでDeleteしているhRgn1, hRgn2はどのリージョン(どのリージョンといった方がいいのかわかりませんが)を削除しているのか分かりません。 あと上記のソースとは関係ないのですが hRgn1 = CreateEllipticRgn(10, 10, 100, 100); hRgn2 = CreateEllipticRgn(50, 50, 200, 150); CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR); DeleteObject(hRgn1); DeleteObject(hRgn2); ←もしかしてこれは不要? としたとき DeleteObject(hRgn2);は不要なのでしょうか? 超初心者な質問ですみません。質問の仕方へたですみません。 分かる人お願いします。

  • Windows付属の「ペイント」の使い方

    Windows付属の「ペイント」の、クリップボードについて教えてください。 http://okwave.jp/qa/q8662089.html 上記の質問の回答3番にペイントを使ったやり方が書いてあります。 1.Windows標準の「ペイント」で画像を開く。 2.画像全体をクリップボードにコピーする。 3.ペイントで新規画像を作って、クリップボードを貼り付けする。 私は自然にペイントを開いた後、そのままコピーしておいた写真を貼り付けましたが、クリップボードにコピーする(貼り付ける意味だと思います)ためには、どうやれば良いのでしょうか? クリップボード自体、どこにあるのでしょうか?

  • 再描画されない

    お世話になります。WS_POPUPで作成したウィンドウにGDI+を用いて画像を表示させています。 そのウィンドウに、他のウィンドウ(最大化されていない)を重ねて動かすと、重なっていた部分が再描画されず真っ白になってしまいます。 最大化されたウィンドで隠した場合は正常に表示されます。 VC+2005です。よろしくお願いします。m(__)m //ウィンドウプロシージャWM_PAINT内 hdc = BeginPaint(hWnd, &ps); Image myImage(fn); MoveWindow(hWnd, 0, 0, myImage.GetWidth(), myImage.GetHeight(), 0); Graphics MyGraphics(hdc); MyGraphics.DrawImage(&myImage, 0, 0, myImage.GetWidth(), myImage.GetHeight()); EndPaint(hWnd, &ps);

  • クリップボードの容量を大きくしたい

    Windowsでクリップボードを経由してコピー貼り付けをする場合ですが、画像などでファイルの容量が4MBを超えるとだめのようです。 クリップボードの容量をもっと大きく設定することは出来るでしょうか。

  • WinAPIで画像を更新し続けるには

    本を見ながら、WindowsSDKを使ってビットマップを描画する 所まではできたのですが、動かそうとすると上手くいきません。 ソースを簡略かして載せますと、以下のようにしています。 case WM_KEYDOWN: x++; // static MyDrawBitMap( hWnd, x, 10 ); ------------------------------------------------ void MyDrawBitMap( HWND hWnd, int x, int y ) { hdc = BeginPaint(hWnd, &ps); BitBlt( hdc, x, y, bitmap.bmWidth, bitmap.bmHeight, hMemDC, 0, 0, SRCCOPY); EndPaint(hWnd, &ps); このように書いてますが、ボタンを押しても画面に変化が出ません。 PAINTSTRUCTは再描画が必要な情報に関する構造体だとは解っていま すが、特に変更の必要の無い画像も再描画したい場合の処理はどうす れば良いのでしょうか?よろしくお願いします。

専門家に質問してみよう