HDCを他の領域にコピーする方法

このQ&Aのポイント
  • HDC hdcとhdcMemDCはハンドラへのポインタであり、hdcMemDCをhdcに書き写す方法が分かりません。
  • hdcMemDCをhdcに書き写すためには、一般的にはAPIフックが必要です。
  • APIフックや手修正を回避するためには他の方法を探す必要があります。
回答を見る
  • ベストアンサー

HDCを他の領域にコピーするには?

HDC hdc = CreateDC("WINSPOOL","プリンタの名前",NULL,NULL); ....(1)プリンタのHDCの作成 HDC hdcMemDC = CreateCompatibleDC(hdc); ....(2)前者と同じ仕様のメモリーHDCの作成 hdcとhdcMemDCはハンドラへのポインタだと思います hdc ....(ポインタ)....... hdcの内容 (A) hdcMemDC ....ポインタ.......hdcMemDCの内容 (B) もしBをA領域に書き写せば TextOut(hdc,0,0,"メモリーDCに書き込めると思います",100); とするとプリンタにではなくメモリ-DCに書込むと思います   ⇒ BをAに書き写さずTextOut(hdcMeMDC,0,0,"メモリーDCに書き込めると思います",100);と同じ結果になるでしょう ところが『BをAに書き写す』方法が分かりません ハンドラの構成、サイズなどの資料を探しましたが適当なものが見つかりません ご存知でしたら教えてください 【追加説明】 TextOut(hdc,0,0,"メモリーDCに書き込めると思います",100); のステートメントを TextOut(hdcMeMDC,0,0,"メモリーDCに書き込めると思います,100); にするには一般的にはAPIフックが必要になります ⇒ もちろん全ソースの手修正でも可能ですが...... APIフックも手修正も回避したいのです

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

デバイスコンテキストのハンドル(HDC)が何らかのメモリブロックへのポインタであると考えていらっしゃるようですが、その考えは捨てましょう。 Windows APIで「ハンドル」とは「オブジェクトを指す識別子」を示します。便宜上、型としてはポインタ型(の別名)として表されますが、実体はポインタ(メモリアドレス)とは限りません。 オブジェクトの種類によっては実際にポインタである場合もあるかもしれませんが、それ以外にもテーブルのインデックスだったり、その他の値だったりします。少なくともGDIオブジェクトは16bitアプリとの互換性のためにハンドルが16bitの範囲内に制限されているので、実際のアドレスである可能性は低いでしょう。 なぜそのようなコピーをする必要があるのかは分かりかねますが、APIフックするのであれば、そこで横取りでも何でもすればよいのでは。

sato-may
質問者

お礼

ご指導ありがとうございます プリンターに関する全てのAPIをフックしようと考えたのです でもプリンターAPIは星の数より沢山あります いちいちフックするのは手間が掛かります そこでフックの代わりにhdcを付け替えてやろうと思ったのです これならば簡単でしょう! でも諦めました 別の方法を模索します ← 実はAPIフックを回避する為まだジタバタしておりますので、今後も宜しくお願い申し上げます ありがとうございました

関連するQ&A

  • StartPage(hdc)のhdcはプリンタだけ

    StartPage(hdc)のhdcは必ずプリンタですか? Windows API に StartPage(hdc)、 EndPage(hdc)があります hdcにはプリンタのデバイスコンテキストのハンドラーを指定します ここで逆説的な質問です 『StartPage、EndPageをAPIフックして捕まえたhdcは必ずプリンタもしくはプリンタコンパティブルのメモリーDCですか?』 プリンタ類似以外のデバイスにStartPage、EndPageのAPIが指定されることはありますか?

  • プリンタBMP領域のサイズは?

    プリンタと同じメモリDCを作り、そこに書き込んだものをBitBltでコピーして印刷します ← サンプルのコードを参照させて頂きましたので多分間違えは無いと思います ところが確保すべきBMP領域(プリンタのサイズ)が分りません ?????????の箇所に設定すべき定数は何処を参照すれば良いのでしょうか? 困っております、ぜひご指導願います HDC hdc; DOCINFO docinfo; memset(&docinfo, 0, sizeof(DOCINFO)); docinfo.cbSize = sizeof(DOCINFO); docinfo.lpszDocName = L"testprint"; hdc = CreateDC(L"EPMJ3", L"Canon MP280 series Printer", NULL, NULL); StartDoc(hdc, &docinfo); StartPage(hdc); HDC hdcMem = CreateCompatibleDC (hdc); int Xsize = ???????????????? int Ysize = ???????????????? HBITMAP hDrawBmp =CreateCompatibleBitmap(hdc,Xsize,Ysize); SelectObject (hdcMem,hDrawBmp); TextOut(hdcMem, 0, 0 , L"プリンタのBMP領域の大きさは何処で分りますか?", 100); BitBlt(hdc, 0, 0,Xsize, Ysize, hdcMem, 0, 0, SRCCOPY); EndPage(hdc);

  • UNICODE指定のプロジェクトで関数Wの呼出し?

    .NET VC++で簡単な印刷プログラムを作りました hdc = CreateDC(TEXT("EPMJ3"), TEXT("Canon MP280 series Printer"), NULL, NULL);・・・(1) StartDoc(hdc, &docinfo);                           ・・・(2) StartPage(hdc); TextOut (hdc, 10, 200,L"テスト印刷の1行目です。", 12);           ・・・(3) TextOutW(hdc, 10, 100,L"テスト印刷の2行目です。", 12);           ・・・(4)  EndPage(hdc); EndDoc(hdc); DeleteDC(hdc); プロジェクトの文字コードはUNICODEを指定しております (1)はCreateDocW関数 (2)はStartDocW関数が呼ばれます (3)は当然TextOutW関数になるだろうと思っていたら、TextOutA関数が呼ばれいます 試しに(4)のように直接TextOutW関数を指定してみたら、これも結果に於いてTextOutA関数が呼ばれています    【以上の事柄はAPIフックを仕掛けて調べました】 なぜ私のコンパイラはUNICODE用のTextOut関数を呼出してくれないのですか????

  • プリンターであるか否かの判断?

    特殊な目的の為、文字列変数Deviceを受取りその内容がプリンターを示すものであれば、APIのCreatDCでプリンターのHDCを作成します そしてそのプリンターのHDCを使用してStartDoc、StartPage、Textout等の一連の印刷動作をしたいと思います それには先ず文字列変数Deviceの内容がプリンターを示しているか? を判別しなくてはなりません 色々調べましたら WINSPOOL である場合はプリンターです 内容が NULL(空白)であればプリンターと判断すべきらしいです また内容が "ディスプレイ" ならば当然除外します しかしこんな判定法で宜しいのでしょうか? 特に文字列変数Deviceの内容が、コントロールパネル⇒デバイスとプリンター によって表示される Canon MP280 series Printer などの具体的なプリンター名称であった場合不安です 文字列変数Deviceの内容がプリンターを示しているか否かを判定するAPIなどはありませんが? また他の手段で簡単に判別する方法をご存知でしたら教えて下さい 宜しくお願い申し上げます

  • CreateDCA、CreateDCWのパラメータ

    HDC CreateDC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutPut, CONST DEVMODE *lpInitData)にはUnicode版とANSI版が実装されます よってCreateDCAでは HDC CreateDCA(PCTSTR lpszDriver, PCTSTR lpszDevice, PCTSTR lpszOutPut, CONST DEVMODE *lpInitData) CreateDCWでは HDC CreateDCW(LCPWSTR lpszDriver, LCPWSTR lpszDevice, LCPWSTR lpszOutPut, CONST DEVMODE *lpInitData) と定義されているのだと思い、上記の形式で呼び出しましたがエラーとなってしました Run_Time check Failure #0- The Value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling conversion with a function pointer declared with a different calling conversion. なぜCreateDCではなくCreateDCAとCrateDCWを直接呼び出すような面倒なことをしているかというと、APIフックでCreateDCを引っ掛けたいのです CreateDCはCreateDCA、CreateDCWになってしまうのでCreateDCではフック出来ません そこでCreateDCA、CreateDCWでフックして当方の処理を行い、その後で本来のCreateDCA、CreateDCWを呼び出しております ところが呼出し方が悪いらしく上記の英文エラーが出てしまいます CreateDCA、CreateDCWで検索したのですが適当な資料が見当たりません 目下のところ手も足も出ません CreateDCA、CreateDCWのパラメータ指定法(多分エラーの原因だろうと思っていますので・・・)をご存知でしたらご指導願います

  • 検索系ソフトは如何にして検索結果画面を印刷するのか

    プリンタ出力APIの代表的なもの TextOut、ExtTextOut、DrawText、DrawTextEx のAPIフックをしました 一般のアプリはもちろん、Word、Execl、秀丸、メモ帳などは確実に印刷の最中にこれらのAPIをフックします ところがGoogle、Yahoo、Gooなどの検索結果画面を印刷しても、これらのTextOut、ExtTextOut、DrawText、DrawTextExのAPIをフックすることはありませんでした 検索系のソフトは一般のAPIを使用せず、何か特別の印刷APIを持っているのでしょうか? それともHTML文で表示した画面はAPI印刷しないのでしょうか? なにかヒントがありましたら教えてください、お願いします

  • AlphBlendとExcel???

    自社で作成した特定の印刷プログラム(4ケあります)とWord全部の印刷ドキュメントには取扱注意を要する情報が印刷されています これらの特定印刷プログラムやWordで印刷したドキュメントの取扱注意を促すため、用紙全体を薄い黄色に印刷しています まるで用紙全体に黄色いカバーを掛けたように見えますので、充分な注意喚起が出来ます 黄色いカバーをする方法は以下のように単純です 印刷開始のトリガーになるAPIであるEndPageにAPIフックを仕掛けます 【APIフックは ADVANCED WINDOWS 著者 Jeffrey Ricther 発刊元 Microsoft社 を参考にさせて頂きました】 EndPageをフックしたらプログラムが自社開発した特定印刷プログラム、またはWord文書であるか否かを判定します これにはGetModuleFileNameWを呼出し、戻り値の内容を調べます リスト(1)を箇所です 4ケの特定印刷プログラム、Word文書である際には次の処理(薄い黄色でカバー)に流し、他の場合にはいきなり(3)の本物のEndPageに移します 薄い黄色でカバーする方法は、まずプリンターと同じメモリーDCを作ります そのメモリーDC全体を黄色に塗り潰します メモリーDCに作った黄色イメージを10%の透明度でプリンタ領域に上書きします すると実際に印刷された用紙は取扱注意を促す黄色になります 具体的なフックプロセスの主要部分は次の通りです 【実際にはもっとゴチャゴチャしていますが、話を単純化するため枝葉をカットしてあります】 int WINAPI Hook_EndPage(HDC hdc) { (1)GetModuleFileNameWでプログラム名を調べ、特定の印刷プログラム・Word文書であれば次の処理をする もし異なればイキナリ(3)へ飛ばします int Xsize = GetDeviceCaps(hdc, HORZRES); //プリンタの領域サイズを調べる int Ysize = GetDeviceCaps(hdc, VERTRES); hdcMemDC = CreateCompatibleDC(hdc); //プリンタと同じメモリーDCを作る HBITMAP hDrawBmp = CreateCompatibleBitmap(hdc,Xsize,Ysize); //調べたプリンタサイズと同 一のビットマップを作る SelectObject (hdcMemDC, hDrawBmp); //ビットマップをメモリーDCに結び付ける HPEN NEWPEN,OLDPEN; NEWPEN = CreatePen(PS_DASH, 2, RGB(255,255,000)); //黄色ペンを作る OLDPEN = (HPEN)SelectObject(hdcMemDC,NEWPEN); //作った黄色ペンをメモリーDCに結び付ける HBRUSH NEWBRUSH,OLDBRUSH; NEWBRUSH = CreateSolidBrush(RGB(255,255,000)); //黄色のブラシを作る OLDBRUSH = (HBRUSH)SelectObject(hdcMemDC,NEWBRUSH); //作った黄色ブラシをメモリーDCに結び付ける Rectangle(hdcMemDC,0,0,Xsize,Ysize); //黄色ペン、ブラシでメモリーDC全体を真黄色にする SelectObject(hdcMemDC,OLDPEN); //ペンとブラシを元に戻す SelectObject(hdcMemDC,OLDBRUSH); ここを(2)とします(後で説明します)   //メモリーDCに作成した黄色イメージ全体を10%の透明度でプリンタ領域に上書きする BLENDFUNCTION blendFunction; ::memset (&blendFunction, 0, sizeof(blendFunction)); //ゼロクリア   blendFunction.BlendOp = AC_SRC_OVER;   blendFunction.BlendFlags = 0; blendFunction.SourceConstantAlpha = 256/10;  ← 10%の透明度を指定   blendFunction.AlphaFormat = 0;   bool rtn = AlphaBlend(hdc, 0, 0, Xsize, Ysize, hdcMemDC, 0, 0, Xsize, Ysize, blendFunction);   //オリジナルEndPageを呼び出す   int nResult = ((PFNENDPAGE)(PROC) g_EndPage)(hdc);   (3)   return nResult; } このEndPageフックを仕掛けるとC#、C++で作った自社の特定印刷プログラムと全てのWord文書は意図した通り黄色いカバーが掛って印刷されます ところが今回、Excel文書も黄色いカバーを掛けることになりました (1)の箇所でExcelも選別してやればOKになるだろうと安易に考えていましたが、実際にテストしてみると次のような現象が発生してNGなのです Excel文書は従前のごとく印刷されます(黄色いカバーが掛っていません) 次に10%の透明度で印刷された黄色い用紙が出てきます すなわちプリンタ領域に出力されたExcel文書とメモリーDCの黄色いイメージが重ならず別々に印刷されてしまいます このとき印刷中のExcel画面には   現在1/1ページを印刷中です   ⇒ 添付画像を参照ください と表示されますので、Excel自体は1ページの文書を印刷しているつもりなのでしょう Excel文書の後に黄色いカバーがくっついていると思っているのでしょう なぜAlphBlend APIはメモリーDCイメージをExcelプリンター領域に重ねてくれないのでしょうか? まるでExcelが自分の出力領域にロックを掛けているような印象です 念の為、(2)に SetTextAlign (hdc, 0);    //テキスト配置オプションではカレントポジションを使用しない MoveToEx(hdc, 0, 0, NULL);  //カレントポジションをゼロに戻す の2ラインを入れて、印刷カレントポジションを原点に戻しても結果は同一でした 質問】 1. なぜExcel文書だけ黄色いカバーが重ならないのでしょうか? 2. Excelの印刷範囲指定操作    印刷するセルを選択 ⇒ ページレイアウト ⇒ 印刷範囲 ⇒ 印刷範囲の設定 が関係しているのではないかとの参考意見を同僚がくれました では上記の操作はどのようなAPIを出しているのでしょうか? もしそのAPIが分かればフックして調べてみたいと思います このExcel文書に黄色いカバーを掛けることで相当な時間を費やしてしまいました でも手掛かりが全くなく困っております どんなヒントでも結構です、ぜひ教えてください、お願い申し上げます

  • 出来上がった印刷イメージをボカす方法???

    .NETのC++を使用して印刷プログラムを組んでいます 定石通りに CreateDC StartDoc StartPage ・ ・ (1) ・ ・ EndPage  (2) EndDoc DeleteDC としております StartPageからEndPageの間の(1)の部分でベタベタと文字やイメージを書込んでいます 主題】 ⇒ 全てを書込んだ(2)の直前で作上げた印刷イメージ(文字、画像の全て)をハーフトーンにボカしたのです (1)の部分は複雑でもうこれ以上手を加えられません 各々のTextOut等のAPIの呼出し方法を修正せず、EndPageの直前で印刷イメージを一括してボカす方法があればご指導願います ??? 便利なAPIはありませんか ???

  • 別関数に渡す変数のポインタが難しい

    構造体初心者で、ポインタもよく分かっていません。 12, 8 と表示するつもりのソースだけど、実行結果は違っていました。 直してください。 ソースは長いけど、スケルトンに構造体とTextOutを付けたぐらいのものです。 #include <windows.h> struct MYOBJ { int a; int b; }; LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int) { MSG msg; WNDCLASS wc; 投稿できなかったからここを消しました。 wc.lpszClassName = "x"; if(RegisterClass(&wc) == 0)return 0; HWND hWnd = CreateWindow("x","",WS_OVERLAPPEDWINDOW|WS_VISIBLE,0,0,320,240,NULL,NULL,hInst,NULL); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } void myfunc(struct MYOBJ *obj)//ここが違うかもしれません。 { obj->a += 2; obj->b -= 2; } LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { HDC hDC; PAINTSTRUCT ps; char buf[30]; switch(uMsg) { case WM_CREATE: struct MYOBJ myobj; myobj.a = 10; myobj.b = 10; myfunc(&myobj);//ここが違うかもしれません。 return 0; case WM_PAINT: hDC = BeginPaint(hWnd, &ps); wsprintf(buf, "%d, %d", myobj.a, myobj.b); TextOut(hDC, 0, 0, buf, strlen(buf)); EndPaint(hWnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; default: return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; }

  • ラスプリンタとは何ですか?

    APIのGetDeviceCapsの戻り値を使用して、デバイスがプリンタであるか否かを判定しています HDC MyHDC = CreateDC(lpszDriver, lpszDevice, lpszOutput, lpInitData); if (GetDeviceCaps(MyHDC, TECNOLOGY) == DT_RASPRINTER) { ここではプリンターの処理をしています } else { プリンター以外の処理をしています } 戻り値がDT_RASPRINTERであれば、プリンタであると思っております ☆そこで質問です☆ (1) RASPRINTERとは何ですか? (2) コントロールパネル ⇒ デバイスとプリンタ の操作によって表示される色々な入出力装置とは如何なる関係があるのでしょうか? 色々調べましたが判然と致しません 宜しくご指導お願い申し上げます

専門家に質問してみよう