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文書に黄色いカバーを掛けることで相当な時間を費やしてしまいました
でも手掛かりが全くなく困っております
どんなヒントでも結構です、ぜひ教えてください、お願い申し上げます
お礼
ありがとうございます ご助言の通りディスプレイに対してテストしたことがあります ごく普通にStartPage/EndPageは正常終了しました でもこれは私の環境の特異現象である恐れがありましたので、質問させて頂いたのです 実際にテストした結果以外に結論はありませんでしょうか? 大変参考になりました ありがとうございました