再描画(WM_PAINT)が変

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
爺プログラマー

再描画(WM_PAINT)が変

#1

投稿記事 by 爺プログラマー » 15年前

爺プログラマーです何時もお世話になります。

CreateWindowEx(0, CLASSNAME, CLASSNAME,
WS_OVERLAPPED| WS_SYSMENU| WS_CAPTION| WS_BORDER| WS_VISIBLE |WS_EX_TOPMOST,
Wnd_x, Wnd_y, Wnd_x_size, Wnd_y_size,HWND_DESKTOP, NULL, hThisInst, NULL);


while(loop_flag)
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))//GetMessage()は待機型
{
TranslateMessage(&msg);
DispatchMessage(&msg);
  }
Sleep(10);




InvalidateRect(h_MainWnd,NULL,FALSE );

}//while(loop_flag)


このようにして再描画をしていますがこの画面が例えばノートパッドを開くと消され閉じると再びこの画面が現れるのですが、コンボボックスやボタンが消えています。
この時この画面を少し移動させると全て表示されます。
InvalidateRectを削除すると消された後も全て表示されます。
原因がわかりません、解決策お願いします。

シエル

Re:再描画(WM_PAINT)が変

#2

投稿記事 by シエル » 15年前

ウィンドウプロシージャのコードを貼って下さい

爺プログラマー

Re:再描画(WM_PAINT)が変

#3

投稿記事 by 爺プログラマー » 15年前

少し長いですが、よろしくお願いします。



LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HFONT AppFont;
HFONT AppFont1;
HBRUSH hBrush1,hBrush2;
HPEN hPen1,hPen2,hPen3,hPen4;
POINT points[5];
POINT points1[4];
POINT points2[4];
RECT recDisplay;

switch(uMsg)
{
case WM_CREATE:

GetClientRect( hWnd, &recDisplay );//クライアント領域
//recDisplay.top
//recDisplay.left
SizeX = recDisplay.right;
SizeY = recDisplay.bottom;//196 134

Y1=SizeY*0.06;
Y2=SizeY*0.20;
Y3=SizeY*0.38;
Y4=SizeY*0.63;
Y5=SizeY*0.78;

InitCommonControls();

CreateComboBox(hWnd);
CreateButton(hWnd);

AppFont = CreateFont(16,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,SHIFTJIS_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
FIXED_PITCH,"MS ゴシック");

SendMessage( h_Buttonkakutei, WM_SETFONT, (WPARAM)AppFont, MAKELPARAM(FALSE,0) );
SendMessage( h_Buttonplay, WM_SETFONT, (WPARAM)AppFont, MAKELPARAM(FALSE,0) );
SendMessage( h_ButtonDelete, WM_SETFONT, (WPARAM)AppFont, MAKELPARAM(FALSE,0) );
SendMessage( h_Buttonstop, WM_SETFONT, (WPARAM)AppFont, MAKELPARAM(FALSE,0) );
SendMessage( h_ComboBox1, WM_SETFONT, (WPARAM)AppFont, MAKELPARAM(FALSE,0) );

// DeleteObject( AppFont );ここでリリースしてはいけないプログラム終了まで保持
break;

case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
AppFont1=CreateFont(16,0,0,0,FW_NORMAL,0,0,0,SHIFTJIS_CHARSET,
OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,FIXED_PITCH,"MS ゴシック");
SelectObject(hdc,AppFont1);
SetTextColor(hdc, RGB(150,150,150));
TextOut(hdc, 16, Y1, "選択ファイルの名前の修正と削除",30);
TextOut(hdc, 16, Y4, "選択ファイルの再生(マウスでクリックした位置から再生可能)",58);

DeleteObject(AppFont1);


hBrush1 = CreateSolidBrush(RGB(160, 60, 60));
hBrush2 = CreateSolidBrush(RGB(255, 255, 255));//塗りつぶし
hPen1 = CreatePen(PS_SOLID, 14, RGB(220, 220, 220));
hPen2 = CreatePen(PS_SOLID, 7, RGB(150, 150, 150));
hPen3 = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
hPen4 = CreatePen(PS_SOLID, 2, RGB(100, 100, 100)); //輪郭

//再生バーの表示
SelectObject(hdc , hBrush1);
Rectangle(hdc , 16 , Y5-2 , 514 , Y5+26 );

SelectObject(hdc, hPen1);
MoveToEx(hdc , 28 , Y5+12 , NULL);
LineTo(hdc , 502 , Y5+12);

SelectObject(hdc, hPen2);
MoveToEx(hdc , 28 , Y5+11 , NULL);
LineTo(hdc , 502 , Y5+11);

SelectObject(hdc, hPen3);
MoveToEx(hdc , 28 , Y5+12 , NULL);
LineTo(hdc , 502 , Y5+12);

//スライダー
points[0].x = SL_Point; points[0].y = Y5+1;
points[1].x = SL_Point-5; points[1].y = Y5+10;
points[2].x = SL_Point-5; points[2].y = Y5+23;
points[3].x = SL_Point+5; points[3].y = Y5+23;
points[4].x = SL_Point+5; points[4].y = Y5+12;

SelectObject(hdc , hBrush2);
SelectObject(hdc, hPen4);
Polygon( hdc, points, 5 );

DeleteObject(hPen4);
DeleteObject(hPen3);
DeleteObject(hPen2);
DeleteObject(hPen1);
DeleteObject(hBrush2);
DeleteObject(hBrush1);

vol_wt(hdc);

ReleaseDC(hWnd,hdc);
EndPaint(hWnd, &ps);
break;

case WM_LBUTTONDOWN:
mouse_dw=1; mouse_dw1=1;
break;

case WM_LBUTTONUP:
mouse_dw1=0;
break;

case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_KAKUTEI:
name_chg = 1;
break;
case IDC_DELETE:
delete_flag = 1;
break;
case IDC_PLAYBUTTON:
if(!play_flag)
{
play_flag = 1;//DS起動
Stop=0;
}

if(play_flag==2)
{
if(Stop)
{
lpSecondary->Play( 0,0,DSBPLAY_LOOPING );
}
if(!Stop)
{
lpSecondary->Stop();
}

if(Stop)
{Stop=0;}
else
{Stop=1;}
}
break;
case IDC_STOPBUTTON:
if(play_flag == 2)//再生中?
{
play_flag = 0;
lpSecondary->Stop();
Exit();
}
break;

case IDC_COMBOBOX://選択項目が変更されたとき
if(HIWORD(wParam) == CBN_SELCHANGE)
{
i = SendMessage(h_ComboBox1, CB_GETCURSEL, 0, 0);
// 文字列の取得
SendMessage(h_ComboBox1, CB_GETLBTEXT, (WPARAM)i, (LPARAM)FILENAME);
SetWindowText(h_EditBox,FILENAME);
}
break;
}
break;

case WM_DESTROY:
PostQuitMessage(0);
loop_flag = 0;
if(play_flag == 2)//再生中?
{
play_flag = 0;
lpSecondary->Stop();
Exit();
}
break;

default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}

爺プログラマー

Re:再描画(WM_PAINT)が変

#4

投稿記事 by 爺プログラマー » 15年前

ウインドープロシージャーの中で呼び出している関数です。

別に関数にするまでもないのですが・・・

void vol_wt(HDC hdc)
{
HPEN hPen1,hPen2,hPen3,hPen4;
POINT points[5];
POINT points1[4];
POINT points2[4];
HBRUSH hBrush1;

i = (Volume/140) + 45 + 590;


//つまみ
points[0].x = i-5; points[0].y = Y4-6;
points[1].x = i-5; points[1].y = Y4+10;
points[2].x = i+5; points[2].y = Y4+10;
points[3].x = i+5; points[3].y = Y4-6;

//スピーカーアイコン
points1[0].x = 575; points1[0].y = Y4-9;
points1[1].x = 565; points1[1].y = Y4-4;
points1[2].x = 565; points1[2].y = Y4+6;
points1[3].x = 575; points1[3].y = Y4+11;
points2[0].x = 565; points2[0].y = Y4-4;
points2[1].x = 558; points2[1].y = Y4-4;
points2[2].x = 558; points2[2].y = Y4+6;
points2[3].x = 565; points2[3].y = Y4+6;

hBrush1 = CreateSolidBrush(RGB(255, 255, 255));//塗りつぶし
hPen1 = CreatePen(PS_SOLID, 1, RGB(160, 60, 60));
hPen2 = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
hPen3 = CreatePen(PS_SOLID, 20, RGB(255, 255, 255));
hPen4 = CreatePen(PS_SOLID, 3, RGB(180, 180, 180)); //輪郭
SelectObject(hdc, hBrush1);

SelectObject(hdc, hPen3);
MoveToEx(hdc , 590-2 , Y4+2 , NULL);
LineTo(hdc , 635+2 , Y4+2);
SelectObject(hdc, hPen2);
MoveToEx(hdc , 590-5 , Y4+2 , NULL);
LineTo(hdc , 635+5 , Y4+2);
SelectObject(hdc, hPen4);
Polygon( hdc, points, 4 );
SelectObject(hdc, hPen1);
Polygon( hdc, points1, 4 );
Polygon( hdc, points2, 4 );
DeleteObject(hPen4);
DeleteObject(hPen3);
DeleteObject(hPen2);
DeleteObject(hPen1);
DeleteObject(hBrush1);
}

シエル

Re:再描画(WM_PAINT)が変

#5

投稿記事 by シエル » 15年前

すいません。一度InvalidateRectの第3引数をTRUEにしてどうなるか教えてもらえますか?

爺プログラマー

Re:再描画(WM_PAINT)が変

#6

投稿記事 by 爺プログラマー » 15年前

ありがとうございます。
早速試しましたが、立ち上げからコンボボックスとボタンが表示されません。
ペイントイベントのグラフィックと文字は表示されています。
フォーカスを外して再び戻しても同様に表示されません。

シエル

Re:再描画(WM_PAINT)が変

#7

投稿記事 by シエル » 15年前

ウィンドウ作成時の親ウィンドウハンドルが「HWND_DESKTOP」でInvalidateRectで呼び出している、
ウィンドウハンドルが「h_MainWnd」になってますが、これは同じウィンドウハンドルですか?

それと、もしよろしければ、ウィンドウクラス登録のコード、ボタン、コンボボックス作成時のコードも貼って下さい。

爺プログラマー

Re:再描画(WM_PAINT)が変

#8

投稿記事 by 爺プログラマー » 15年前

よろしくお願いします。

wce.cbSize = sizeof(WNDCLASSEX);
wce.hInstance = hThisInst;
wce.lpszClassName = CLASSNAME;
wce.lpfnWndProc = WinProc;
wce.style = NULL;
wce.hIcon = NULL;
wce.hIconSm = NULL;
wce.hCursor = LoadCursor(NULL, IDC_ARROW );
wce.lpszMenuName = NULL;
wce.cbClsExtra = 0;
wce.cbWndExtra = 0;
wce.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
if(!RegisterClassEx(&wce)) return 0;


hDeskWnd = GetDesktopWindow();
GetWindowRect( hDeskWnd, &recDisplay );
Wnd_x = ( recDisplay.right - Wnd_x_size ) / 2; //左上x座標
Wnd_y = ( recDisplay.bottom - Wnd_y_size ) /2; //左上y座標

h_MainWnd = CreateWindowEx(0, CLASSNAME, CLASSNAME,
WS_OVERLAPPED| WS_SYSMENU| WS_CAPTION| WS_BORDER| WS_VISIBLE |WS_EX_TOPMOST,
Wnd_x, Wnd_y, Wnd_x_size, Wnd_y_size,
HWND_DESKTOP, NULL, hThisInst, NULL);





long CreateComboBox(HWND hWnd)
{
WIN32_FIND_DATA lpFileData;
HANDLE hFind;

h_EditBox = CreateWindowEx(
0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT |ES_AUTOHSCROLL,
16, Y2, 500, 25,
hWnd, (HMENU)IDC_EDITBOX, h_Inst, NULL);

h_ComboBox1 = CreateWindowEx(
0, "COMBOBOX", "",
WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_DROPDOWNLIST|CBS_SORT|CBS_NOINTEGRALHEIGHT,
16, Y3, 500, 220,
hWnd, (HMENU)IDC_COMBOBOX, h_Inst, NULL);


strcpy(FILENAME+260,INI_BUFF+Folder);
strcat(FILENAME+260,"\\*.wav");
List_len = 0;

//ファイルの検索
hFind = FindFirstFile(FILENAME+260, &lpFileData);

next_file:

strcpy(FILENAME,lpFileData.cFileName);
j=(strlen(FILENAME))-4;
FILENAME[j]=0;//拡張子削除

SendMessage(h_ComboBox1, CB_ADDSTRING, 0, (LPARAM)FILENAME);

if(List_len < j)List_len = j;

if(FindNextFile(hFind,&lpFileData)!=0)goto next_file;

FindClose(hFind);

i=SendMessage(h_ComboBox1, CB_GETCOUNT, 0, 0)-1;//行数取得(最後の行を初期表示にする)
SendMessage(h_ComboBox1, CB_SETCURSEL, i, 0);

SendMessage(h_ComboBox1, CB_GETLBTEXT, (WPARAM)i, (LPARAM)FILENAME);
SetWindowText(h_EditBox,FILENAME);//最後の行をテキストボックスへ

SendMessage(h_ComboBox1,CB_SETDROPPEDWIDTH,List_len * 8.52,NULL);//最大幅設定
return 0;
}






long CreateButton(HWND hWnd){
h_Buttonkakutei = CreateWindowEx(
0, "BUTTON", "入力確定",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
522, Y2, 70, 24,
hWnd, (HMENU)IDC_KAKUTEI, h_Inst, NULL);
h_ButtonDelete = CreateWindowEx(
0, "BUTTON", "削除",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
530+70, Y2, 40, 24,
hWnd, (HMENU)IDC_DELETE, h_Inst, NULL);

h_Buttonplay = CreateWindowEx(
0, "BUTTON", "再生停止",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
522, Y5, 70, 24,
hWnd, (HMENU)IDC_PLAYBUTTON, h_Inst, NULL);
h_Buttonstop = CreateWindowEx(
0, "BUTTON", "終了",
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
520+80, Y5, 40, 24,
hWnd, (HMENU)IDC_STOPBUTTON, h_Inst, NULL);
return 0;
}

シエル

Re:再描画(WM_PAINT)が変

#9

投稿記事 by シエル » 15年前

う~ん。よく分からないですねぇ。

メインウィンドウ作成時のCreateWindowExの親ウィンドウハンドルにHWND_DESKTOPを指定してますが、
これは何か意味があるのですか?
ちなみにこれをNULLにしてみたらどうなりますか?

爺プログラマー

Re:再描画(WM_PAINT)が変

#10

投稿記事 by 爺プログラマー » 15年前

HWND_DESKTOPをNULLでためしましたが、結果は同じでした。

なお、ハンドルの記述は下記の通りです。


HWND h_MainWnd;//子のハンドル
HWND h_Buttonkakutei,h_Buttonplay,h_ButtonDelete,h_Buttonstop;
HWND h_ComboBox1,h_EditBox;
HINSTANCE h_Inst;



int WINAPI WinMain(HINSTANCE hThisInst,HINSTANCE hPrevInst, LPSTR lpszArgs,int nWinMode)
{
HWND hDeskWnd;
MSG msg;



シエル

Re:再描画(WM_PAINT)が変

#11

投稿記事 by シエル » 15年前

やっぱり原因は良く分かりませんが、
基本的に描画はバックバッファに描画を行い、BITBLTでメインに転送して表示するのが
基本だと思いますので、そのようにしたほうが良いと思います。
このままだとおそらく画面もちらつきますし。

Justy

Re:再描画(WM_PAINT)が変

#12

投稿記事 by Justy » 15年前

 WM_PAINTのときも DefWindowProcが呼ばれるようにしたらどうなりますか?

爺プログラマー

Re:再描画(WM_PAINT)が変

#13

投稿記事 by 爺プログラマー » 15年前

シエル ..上級者さん

実はチラツキがあるため描画順序に配慮しています。

BITBLTを勉強します。DirectXには自信があるのですが・・・




..伝説なるハッカーさん
case WM_PAINT:



ReleaseDC(hWnd,hdc);
EndPaint(hWnd, &ps);
DefWindowProc(hWnd, uMsg, wParam, lParam);
break;

このようにするのですか?

爺プログラマー

Re:再描画(WM_PAINT)が変

#14

投稿記事 by 爺プログラマー » 15年前

自己解決しました!!!

InvalidateRect(h_MainWnd,NULL,FALSE );
UpdateWindow(h_MainWnd);


シエル ..上級者さん
Justy ..伝説なるハッカーさん

感謝します、また宜しくお願いします。

シエル

Re:再描画(WM_PAINT)が変

#15

投稿記事 by シエル » 15年前

UpdateWindowですか。。。おめでとうございます。
私はDirectxを始めたばかりで、まだ全然わからないので、
私がDirectxの質問をした時は助けてくれると助かりますw

ISLe

Re:再描画(WM_PAINT)が変

#16

投稿記事 by ISLe » 15年前

EndPaintの前のReleaseDCは要らないと思います。

SelectObjectで選択したGDIオブジェクトを選択したままDeleteObjectしてるのが気になります。
しばらく動かしているとデスクトップが真っ白になりそうな気がしますがただの気のせいかもしれません。
#デバイスコンテキストといっしょにうまく解放されているかもしれないので。

描画のチラツキは親ウインドウにWS_CLIPCHILDRENスタイルを指定すると直るかもしれません。

爺プログラマー

Re:再描画(WM_PAINT)が変

#17

投稿記事 by 爺プログラマー » 15年前

ISLe ..かけだし さん
的確な回答ありがとうございます。

WS_CLIPCHILDRENでチラツキは全く無くなりました、今までは10ループ毎に表示していましたがこれで毎回ループ表示が出来ます。

>真っ白になりそうな気がしますがただの気のせいかもしれません

気のせいではありません、描画タイミングによりデスクトップにも塗られた時がありました。
Windowsは皆の共有物であることを忘れていました。

hFontOld = SelectObject(hdc, hFont);



SelectObject(hdc, hFontOld);
DeleteObject(hFont);

借りた物はそっくりそのまま返すよう、これからはお行儀よく致します。

dic

Re:再描画(WM_PAINT)が変

#18

投稿記事 by dic » 15年前

HDC に描画してFlipだったような・・・
できたならそれでいいですけどね

爺プログラマー

Re:再描画(WM_PAINT)が変

#19

投稿記事 by 爺プログラマー » 15年前

皆さんに教えて頂いたことを守ってジックリ試験しましたら、やはりダメでした。
時間が経つと、新規作成したウインドー相対ではなくデスクトップ相対のピクセル位置に描画されてしまいました。


dic ..比類無きプログラマー さん今日は・・・

Flipとはどの様に記述するのでしょうか?
具体的に構文を教えてください。
お願いします。

dic

Re:再描画(WM_PAINT)が変

#20

投稿記事 by dic » 15年前

DirectX とあったので、DirectX を使っての描画かと思ったんですが、
上のソースを見るとWIN32AIPを使っての描画のようで、私の勘違いでした

はずしてしまったんですが、聞かれてるので簡単に書くと
LPDIRECTDRAWSURFACE3 pScreen = NULL;
pScreen を初期化
pScreen->Flip(NULL,DDFLIP_WAIT);
のようにするみたいです

というのもDirectXを使ったライブラリがあったのですが、
ハードディスクごとデータが消えたのです
なので、うる覚えです

うる覚えですが、WIN32APi と Direct X を混合すると
結構やっかいな処理になった記憶があります

爺プログラマー

Re:再描画(WM_PAINT)が変

#21

投稿記事 by 爺プログラマー » 15年前

dic ..比類無きプログラマー さん

ご参加ありがとうございます。フリップはDirectXの裏画面と表画面を切り替える操作でしたね。
DirectXでは描画中のチラツキを隠すためにこの操作が基本になります。

また、よろしくお願いします。

閉鎖

“C言語何でも質問掲示板” へ戻る