描画ウインドの保存について

[戻る]
TKO 2009/12/24(木) 19:39:12
パワーポイントの上に透明なウインドを作って
線や図を挿入させ表示というプログラム作っているのですが

パワーポイントで前のページに戻った時
前のページに書き込んだ情報(線,図)を再描画するため

次のページ移るたびにウインドを保存用のウインドに保存して
戻ると描画用ウインドに上書きし
表示させようとしているのですが全く反映されません

HWND g_hDisplayWindow;            // 描画用ウィンドウのハンドル
HWND g_annotation_slide[20];    //各スライドのアノテーションデータ保存用
この二つがそれぞれのウインドハンドルで
以下のように描画用ウインドを生成しています

hWnd = CreateWindowEx(
            WS_EX_LAYERED,    
            szClassName,    
            "DisplayWindow",
            //WS_OVERLAPPEDWINDOW,            
            WS_OVERLAPPED | WS_POPUP,
            0,                    
            0,                    
            Size.x,        
            Size.y,    
            NULL,    
            NULL,
                        hInstance,    
            NULL    
    );

g_hDisplayWindow = hWnd;
ShowWindow(g_hDisplayWindow, nCmdShow);
UpdateWindow(g_hDisplayWindow);

SetWindowPos(g_hDisplayWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

そして次のスライドに移るときに
g_annotation_slide[g_nSlideIndex]=g_hDisplayWindow;//ウインドを保存

前のスライドに戻ると
g_hDisplayWindow = g_annotation_slide[g_nSlideIndex];
UpdateWindow(g_hDisplayWindow);
で前のウインドを表示させたいのですが反映されません

描画ウインドに線などを書き込みすることはできます
よろしくお願いします

επιστημη [E-Mail] [HomePage] 2009/12/25(金) 05:11:28
> g_hDisplayWindow = g_annotation_slide[g_nSlideIndex];
> UpdateWindow(g_hDisplayWindow);
> で前のウインドを表示させたいのですが反映されません

その通り。反映さえrません。
ハンドルがすべての情報を保持しているわけではありませんから。
# というより、ハンドルはまさしく"取っ手"でしかなく、描画情報はほとんど保持して
いません。

rock 2009/12/25(金) 08:16:08
DIBデータを保持すればいいと思います。
imgctl.dllを使うと簡単にできます。
void SaveDIB(HDIB *phDIB, HWND hWnd)
{
HDC hDC = GetDC(hWnd);
RECT Rect;
GetClientRect(hWnd, &Rect);
// DIBデータを保存(※DCtoDIB()はimgctl.dllの関数)
*phDIB = DCtoDIB(hDC, Rect.left, Rect.top, Rect.right - Rect.left, Rect.bottom -
Rect.top);
ReleaseDC(hWnd, hDC);
}

描画はDIBtoDCex2()などを使えばいいと思います。

回答になってなかったらすみません。

TKO 2009/12/25(金) 17:19:24
回答ありがとうございます
本当に初歩的な質問ですみません

c++で開発しているのですがimgctl.dllのインポート方法が分かりません
プログラムに
#import <imgctl.dll>
と宣言し

デバッグディレクトリ下にimgctl.dllを置いているのですが
エラー    fatal error C1083: タイプ ライブラリ ファイルを開けません。
'imgctl.dll': No such file or directory    

というエラーが出てしまいます
本当に初歩的な質問ですみません

επιστημη [E-Mail] [HomePage] 2009/12/25(金) 19:31:31
マニュアル読みました?

rock 2009/12/25(金) 23:47:55
#include "imgctl.h"
#pragma comment(lib, "imgctl.lib")
です。
imgctl.dll と imgctl.h と imgctl.lib が必要です。

rock 2009/12/27(日) 01:12:17
なんか冗長な回答をしていました。
DCを保存するだけでいいですね。

rock 2009/12/27(日) 04:53:24
もう少し詳しく書きます。

1:メモリDCを作成する。
2:コピー元のウィンドウのDCをメモリDCにコピーする。
3:メモリDCをコピー先のウィンドウのDCにコピーする。
2,3のコピーはBitBlt()を使って下さい。

TKO 2009/12/28(月) 23:36:24
rockさんありがとうございます

現在

次のスライドに移ると
PostMessage(g_hDisplayWindow, WM_COMMAND, ID_ANNOTATIONSAVE, NULL);
//スライドを保存
PostMessage(g_hDisplayWindow, WM_COMMAND, ID_ALLCLEAR, NULL);
//すべての書き込みを消す

PostMessage(g_hDisplayWindow, WM_COMMAND, ID_ANNOTATIONLODE, NULL);
//書き込み情報をロード
UpdateWindow(g_hDisplayWindow)
描画ウインドウの更新

関係ないところは省きましたが
だいたいこのような手順でプログラムを作成したのですが反映されません

ID_ANNOTATIONSAVEの中身は

hDC = GetWindowDC(hWnd);//現在のウインドウのデバイスコンテキスト取得
hmdc_save[g_nSlideIndex] = CreateCompatibleDC(hDC);
BitBlt( hmdc_save[g_nSlideIndex], 0, 0, SizeX, SizeY, hDC, 0, 0, SRCCOPY );
//各スライドのデバイスコンテキストに保存
ReleaseDC(hWnd, hDC);



ID_ANNOTATIONLODEの中身は
hDC = GetDC(hWnd);
BitBlt(hDC , 0, 0, SizeX, SizeY, hmdc_save[g_nSlideIndex], 0, 0, SRCCOPY );
//各スライドのデバイスコンテキストをコピー            
ReleaseDC(hWnd, hDC);



hmdc_save[20]は書き込み情報保存用のデバイスコンテキスト
g_nSlideIndexはスライド番号です

よろしくお願いします

rock 2009/12/29(火) 04:11:16
サンプル書いてみました。
何にもチェックしてないので、コンパイル通らないかも。

// 裏画面構造体
typedef struct tagbackbuffer
{
&#160;&#160; &#160;HDC hMemDC;
&#160;&#160; &#160;HBITMAP hOldBitmap;
&#160;&#160; &#160;POINT Size;
} BACKBUFFER;
// 裏画面構造体を作成
BACKBUFFER*&#160;CreateBuckBuffer(HWND hWnd)
{
&#160;&#160; &#160;BACKBUFFER* pBB = (BACKBUFFER*)calloc(1, sizeof(BACKBUFFER));
&#160;&#160; &#160;HDC hDC = GetDC(hWnd);
&#160;&#160; &#160;RECT Rect;
&#160;&#160; &#160;GetClientRect(GetDesktopWindow(), &Rect);
&#160;&#160; &#160;pBB->hMemDC = CreateCompatibleDC(hDC);
&#160;&#160; &#160;HBITMAP hMemBitmap = CreateCompatibleBitmap(hDC, Rect.right, Rect.bottom);
&#160;&#160; &#160;pBB->hOldBitmap = SelectObject(pBB->hMemDC, hMemBitmap);
&#160;&#160; &#160;return pBB;&#160;
}
// 裏画面構造体を破棄
void DestroyBackBuffer(BACKBUFFER* pBB)
{
&#160;&#160; &#160;HBITMAP hMemBitmap = (HBITMAP)SelectObject(pBB->hMemDC, pBB->hOldBitmap);
&#160;&#160; &#160;DeleteObject(hMemBitmap);
&#160;&#160; &#160;DeleteDC(pBB->hMemDC);
&#160;&#160; &#160;free(pBB);
}
// ウィンドウのクライアント領域を裏画面構造体にコピー
void CopyToBackBuffer(BACKBUFFER *pBB, HWND hWnd)
{
&#160;&#160; &#160;HDC hDC = GetDC(hWnd);
&#160;&#160; &#160;RECT Rect;
&#160;&#160; &#160;GetClientRect(hWnd, &Rect);
&#160;&#160; &#160;pBB->Size.x = Rect.right;
&#160;&#160; &#160;pBB->Size.y = Rect.bottom;
&#160;&#160; &#160;BitBlt(pBB->hMemDC, 0, 0, pBB->Size.x, pBB->Size.y, hDC, 0, 0, SRCCOPY);
&#160;&#160; &#160;ReleaseDC(hWnd, hDC); &#160; &#160;
}
// 裏画面構造体をウィンドウのクライアント領域にコピー
void CopyToWindow(HWND hWnd, BACKBUFFER* pBB)
{
&#160;&#160; &#160;HDC hDC = GetDC(hWnd);
&#160;&#160; &#160;RECT Rect;
&#160;&#160; &#160;GetClientRect(hWnd, &Rect);
&#160;&#160; &#160;StretchBlt(hDC, 0, 0, Rect.right, Rect.bottom, pBB->hMemDC, 0, 0, pBB->Size.x, pBB->Size.y, 
SRCCOPY);
&#160;&#160; &#160;ReleaseDC(hWnd, hDC);
}

// 使い方
BACKBUFFER* pBB;
// 初期化(WM_CREATEぐらいのタイミングで)
pBB = CreateBackBuffer(hWnd);
// ウィンドウを裏画面にコピー
CopyToBackBuffer(pBB, hWnd);
// 裏画面をウィンドウにコピー
CopyToWindow(hWnd, pBB);
// 解放(WM_CLOSEぐらいのタイミングで)
DestroyBackBuffer(pBB);

rock 2009/12/29(火) 08:22:11
[訂正]
スペル間違い
CreateBuckBuffer()
→CreateBackBuffer()

キャストしていなかった(CreateBuckBuffer()内)
pBB->hOldBitmap = SelectObject(pBB->hMemDC, hMemBitmap);
→pBB->hOldBitmap = (HBITMAP)SelectObject(pBB->hMemDC, hMemBitmap);

一応、動作確認しました。
透明なウィンドウだとどうなるかわかりませんが・・・

TKO 2009/12/30(水) 22:11:51
rockさんありがとうございます
プログラム
参考にさせてもらいます

すみませんが
&#160;&#160;はどういった意味でしょうか
つまらない質問ですいません

rock 2009/12/30(水) 23:01:27
iPhoneのメモ帳から貼りつけたら、変な文字が挿入されてしまいました。
無視して下さい。

TKO 2010/01/06(水) 21:48:24
ありがとうございます

このプログラムではpBB++で次のスライドや
p--で前のスライドの書き込み情報の参照をしたらよろしいのでしょうか??

rock 2010/01/06(水) 23:20:33
ポインタの配列を使うと良いかと。

BACKBUFFER* pBB[20];
// 初期化
for(int i = 0;i < 20;i++)
pBB[i] = CreateBackBuffer(hWnd);
// 解放
for(int i = 0;i < 20;i++)
DestroyBackBuffer(pBB[i]);

// 例:ウィンドウを7番目の裏画面にコピー
CopyToBackBuffer(pBB[7], hWnd);

// 例:13番目の裏画面をウィンドウにコピー
CopyToWindow(hWnd, pBB[13]);

そんなに難しくないはずなので、頑張って下さい。

rock [E-Mail] 2010/01/06(水) 23:52:02
[補足]
もし、コピー元とコピー先のウィンドウのクライアント領域のサイズが同じなら、
CopyToWindow()内のStretchBlt を BitBlt に書き直して下さい。
その方が処理が高速です。
また、BACKBUFFERのメンバ Size が不要になります。

古いスレッドには追加発言できません。