DialogBoxで隠れた画面の表示について – プログラミング – Home

DialogBoxで隠れた画面の表示に...
 
通知
すべてクリア

DialogBoxで隠れた画面の表示について

固定ページ 1 / 2

suzugoya
 suzugoya
(@suzugoya)
ゲスト
結合: 22年前
投稿: 47
Topic starter  

( Win98 VC++ API で作成)
データをFileDialogで メモリデバイス読み込み
Common DialogBoxで隠れていた所にBitBltで表示しようとしても
できません
 (できるときもあります)
表示用のボタンを作りクリックすれば表示しますが
フアイル読み取り後に、そのボタンをSendMessageでよんでも
表示できません
BitBlt後 Sleepを使用すると、Sleepの経過後に画面が消えてしまいます
理由がわかりません
よろしくお願いします


引用解決済
トピックタグ
Wanderer
 Wanderer
(@Wanderer)
ゲスト
結合: 22年前
投稿: 35
 

WM_PAINTに対して描画処理をしていないために、せっかく
描画してもダイアログにクリップされてしまっていて、ダ
イアログが消えても再描画していないから現れない。

というのではないのでしょうか?

はずしていたらごめんなさい。


返信引用
suzugoya
 suzugoya
(@suzugoya)
ゲスト
結合: 22年前
投稿: 47
Topic starter  

WM_PAINT内でBitBltしてみましたが、同じでした
何度も確かめてみましたが。駄目でした
なぜなのでしょうか


返信引用
suzugoya
 suzugoya
(@suzugoya)
ゲスト
結合: 22年前
投稿: 47
Topic starter  

Wandererさん ありがとうございます

書き忘れていました
一旦は描画されるのですが、すぐに消えてしまいます
Sleep()で確認すると、その時間だけ表示されています

WM_PAINT内でBitBltしてみましたが、同じでした
何度も確かめてみましたが駄目でした

DialogBoxが消え、グラフが描画され、再びDialogBoxの亡霊が画面を消しているようです
なぜなのでしょうか


返信引用
Wanderer
 Wanderer
(@Wanderer)
ゲスト
結合: 22年前
投稿: 35
 

InvalidateRect()で画面全領域を無効化してもだめでしょうか?


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

肝心のBitBltの転送元を破棄してしまっているとか。


返信引用
島
 島
(@島)
ゲスト
結合: 23年前
投稿: 238
 

FileDialog でファイルのパス名を取得するところから、画像を画面に表示するところまでの
一連の流れがわかるようにソースを示して下さい

一応、こちらの予想では[ファイル]-[開く]で FileDialog を使おうとなさっているだろうと
見ていて、このハンドラー内で画像ファイルを読み取って、ウィンドーに BitBlt() している
可能性が大きいとも感じていますが、どうでしょうか?


返信引用
suzugoya
 suzugoya
(@suzugoya)
ゲスト
結合: 22年前
投稿: 47
Topic starter  

ソースの一部です
IDM_YOMIKOMIで読み込み、IDM_UEボタンをクリックすればグラフを表示します
しかし、DM_YOMIKOMIの中でSendMessage()を送ってもグラフは瞬間的に表示されるだけです
Sleep(1000)では1秒間だけ表示されます

InvalidateRect()もtryしてみました

case IDM_YOMIKOMI:
GetCurrentDirectory(sizeof(buf),buf);
memset( &ofn, 0, sizeof( OPENFILENAME ) );
ofn.lStructSize = sizeof( OPENFILENAME );
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = datファイル(ニ現象*.dat)\0*.dat\0任意ファイル
(*.*)\0*.*\0\0;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = MAX_PATH;
ofn.Flags = OFN_PATHMUSTEXIST;
ofn.lpstrDefExt = dat;
ofn.lpstrInitialDir= buf;

GetOpenFileName( &ofn );
;//InvalidateRect( hwnd, NULL, TRUE );
hFile = CreateFile( szFileName, GENERIC_READ, 0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL );
dwSize=GetFileSize(hFile,NULL);
_splitpath(szFileName,drive,dir,ffname,ext);
if(dwSize==0)return 0;
if(dwSize>MAXBUF)dwSize=MAXBUF;
if(!ReadFile( hFile, pBuffer[0], dwSize,&dW, NULL )){
SetTextColor(hDC,RGB(240,0,0));
wsprintf(buf,ファイル %s%s がありません,ffname,ext);
DrawText(hDC,buf,strlen(buf),&rectzenp[0],DT_CENTER |
DT_VCENTER | DT_SINGLELINE );
}
CloseHandle(hFile);
//InvalidateRect( hzenPict[0], NULL, FALSE );
SendMessage(hwnd,WM_COMMAND,IDM_UE,0);    //????瞬間だけグラフが現れ

Sleep(1000);
return 0;
case IDM_UE:
//---------グラフを描く
hDC=GetDC(hzenPict[0]); //hzenPict[0] はdialogBoxに隠れる
領域のRECTです
SelectObject(hDC,hPenBlack);
MoveToEx(hDC,0,66-(int)(pBuffer[0][0] /256)/4,NULL);
for(x=1;x<saigo ;x++)
LineTo(hDC,(int)(x * SCRMAX / hyouji) , 66-(int)(pBuffer[0]
[x] /256)/4);
ReleaseDC(hzenPict[0],hDC);
return 0;

/*
hzenPict[0] = CreateWindow(STATIC,
",WS_CHILD | WS_VISIBLE | WS_BORDER | ES_RIGHT,
.......);
*/


返信引用
sugar
 sugar
(@sugar)
ゲスト
結合: 24年前
投稿: 448
 

結局これだと、IDM_UEメッセージを受けた時にしかグラフを描く処理が動きませんよね?
WM_PAINTメッセージの時、何かしてます?
この時にグラフ描かないといけないんですよ、
と、Wandererさんは申しております。


返信引用
tnd
 tnd
(@tnd)
ゲスト
結合: 22年前
投稿: 6
 

WM_PAINTで描画処理を行っていますか?
WM_PAINTで描画処理をせず、独自コマンドハンドラ内で描画処理を行うのはなぜですか?

ダイアログが隠していた領域が見えるようになれば、WM_ERASEBKGND、WM_PAINTが発生し
てデフォルトの動作ではその領域が白く塗りつぶされるでしょう。


返信引用
島
 島
(@島)
ゲスト
結合: 23年前
投稿: 238
 

ボタンを押した事にするのに SendMessage() していますが、PostMessage() に変えて、
Sleep(1000); はそうすると不要になりますから、削除するなり、コメントアウトして下さい

おそらく、これでなさりたい事は実現するでしょうが、適切な方法とはいえません
これについては sugar さんや tnd さんや Wanderer さんが仰っている事なのですが、
再描画でも(つまりこのウィンドーが最小化した後、元のサイズに戻したり、別のウィンドー
で隠れていた部分が(別のウインドーが移動したり、消えたりして)出てきた場合)せっかく
のグラフが消えたり欠けたりしないように出来ないと困りませんかと言う事です

WM_PAINT でも、一旦ファイルを読み込んで、表示するためのボタンを押した場合に備えて
フラグを用意しておいて、フラグの状態に応じて、WM_PAINT でグラフを表示するような
コードになっていれば再描画に対しても困らないでしょう

上のことが出来たら、再描画の度にグラフを描くのではなくて、メモリーDCとビットマップ
とを用意しておけば、ビットマップをメモリーDCに選択しておいて、このメモリーDCに
グラフを描く事で、WM_PAINT では BitBlt() だけで済むように出来るでしょう
(オフスクリーンなどと呼ぶ技法です)


返信引用
suzugoya
 suzugoya
(@suzugoya)
ゲスト
結合: 22年前
投稿: 47
Topic starter  

ダイアログが隠していた領域が見えるようになれば、WM_ERASEBKGND case WM_PAINT:
が発生し

の記述で少し理解ができました

プログラムは、 WM_PAINT の働きがときどき分からなくなりますので
使用しないで作成しました

無効になる可能性のある部分だけ再描画するには
どうすればよいのでしょうか

・WM_PAINTでなければ、無効化されたエリアは描画されない
・従って、メモリデバイスに保存しておいたデータを、無効化されたエリアに
 BitBltしても、無効 
・WM_PAINTが記述されていると、File Dialogを呼び出した時点で
 全画面が消去されてしまうのは、WM_ERASEBKGNDのせい

という理解でよいのでしょうか


返信引用
tnd
 tnd
(@tnd)
ゲスト
結合: 22年前
投稿: 6
 

WM_PAINT内で通常BeginPaintを使うのは御存知ですよね。
その引数LPPAINTSTRUCTを調べれば再描画しなくてはいけない領域が分かるはずです。

> ・WM_PAINTでなければ、無効化されたエリアは描画されない
WM_PAINTは画面が無効化され再描画が必要であることを伝えるためのメッセージですの
で、ここで再描画するのが普通です。

> ・WM_PAINTが記述されていると、File Dialogを呼び出した時点で
>  全画面が消去されてしまうのは、WM_ERASEBKGNDのせい
DefWindowProcがWM_ERASEBKGNDを処理した場合、ウィンドウクラス登録時に指定したブラ
シ(通常は白)で塗りつぶされます。


返信引用
suzugoya
 suzugoya
(@suzugoya)
ゲスト
結合: 22年前
投稿: 47
Topic starter  

皆さん ありがとうございます
この画面は、結果をみてすぐに消してもよい内容なので
再描画は考えていませんでした
ご指摘のあった周辺を調べます 


返信引用
suzugoya
 suzugoya
(@suzugoya)
ゲスト
結合: 22年前
投稿: 47
Topic starter  

1.実行結果
 △FileDialog 呼び出し で無効化領域ができる
PostMessage( IDM_UE );
UpdateWindow(hwnd);   //hwnd はstatic コントロールのhandle
return 0; // このコントロールは無効化領域にある
case IDM_UE:
hDC=GetDC(hwnd);
hDCに描画
  で描画できました
 △PAINTSTRUCT rcPaintで無効化領域を調べてみましたが
  (0,0,0,0)となってしまいました
2.ここでの PostMessage の働きは
    ・IDM_UE Messagaがキューに入る
    ・すぐに制御を返されたWndProcは、DialogBoxで無効化された
     エリアにWM_ERASEBKGND WM_PAINTを処理
    ・その後、キューに入っていた IDM_UEが 実行される
 
  SenMessageでは
     メッセージを処理し終わった後で、制御を返します
  と書いてありますが
    ・FileDialog 呼び出し で無効化領域ができる
    ・メッセージ IDM_UE を処理し、無効化領域に一旦グラフが描かれる
    ・制御を返された WndProc は
      WM_PAINTが記述されていれば全画面を
                いなければ無効化領域だけをWM_ERASEBKGND
      その後 WM_PAINTを処理する

でよいのでしょうか


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました