ページ 11

再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 12:10
by 爺プログラマー
爺プログラマーです何時もお世話になります。

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)が変

Posted: 2010年6月29日(火) 12:19
by シエル
ウィンドウプロシージャのコードを貼って下さい

Re:再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 13:32
by 爺プログラマー
少し長いですが、よろしくお願いします。



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)が変

Posted: 2010年6月29日(火) 13:48
by 爺プログラマー
ウインドープロシージャーの中で呼び出している関数です。

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

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)が変

Posted: 2010年6月29日(火) 18:41
by シエル
すいません。一度InvalidateRectの第3引数をTRUEにしてどうなるか教えてもらえますか?

Re:再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 20:14
by 爺プログラマー
ありがとうございます。
早速試しましたが、立ち上げからコンボボックスとボタンが表示されません。
ペイントイベントのグラフィックと文字は表示されています。
フォーカスを外して再び戻しても同様に表示されません。

Re:再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 20:35
by シエル
ウィンドウ作成時の親ウィンドウハンドルが「HWND_DESKTOP」でInvalidateRectで呼び出している、
ウィンドウハンドルが「h_MainWnd」になってますが、これは同じウィンドウハンドルですか?

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

Re:再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 20:40
by 爺プログラマー
よろしくお願いします。

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)が変

Posted: 2010年6月29日(火) 20:51
by シエル
う~ん。よく分からないですねぇ。

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

Re:再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 21:06
by 爺プログラマー
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)が変

Posted: 2010年6月29日(火) 21:51
by シエル
やっぱり原因は良く分かりませんが、
基本的に描画はバックバッファに描画を行い、BITBLTでメインに転送して表示するのが
基本だと思いますので、そのようにしたほうが良いと思います。
このままだとおそらく画面もちらつきますし。

Re:再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 22:07
by Justy
 WM_PAINTのときも DefWindowProcが呼ばれるようにしたらどうなりますか?

Re:再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 22:21
by 爺プログラマー
シエル ..上級者さん

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

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




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



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

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

Re:再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 22:37
by 爺プログラマー
自己解決しました!!!

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


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

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

Re:再描画(WM_PAINT)が変

Posted: 2010年6月29日(火) 22:41
by シエル
UpdateWindowですか。。。おめでとうございます。
私はDirectxを始めたばかりで、まだ全然わからないので、
私がDirectxの質問をした時は助けてくれると助かりますw

Re:再描画(WM_PAINT)が変

Posted: 2010年6月30日(水) 02:39
by ISLe
EndPaintの前のReleaseDCは要らないと思います。

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

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

Re:再描画(WM_PAINT)が変

Posted: 2010年6月30日(水) 10:00
by 爺プログラマー
ISLe ..かけだし さん
的確な回答ありがとうございます。

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

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

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

hFontOld = SelectObject(hdc, hFont);



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

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

Re:再描画(WM_PAINT)が変

Posted: 2010年6月30日(水) 16:32
by dic
HDC に描画してFlipだったような・・・
できたならそれでいいですけどね

Re:再描画(WM_PAINT)が変

Posted: 2010年6月30日(水) 20:43
by 爺プログラマー
皆さんに教えて頂いたことを守ってジックリ試験しましたら、やはりダメでした。
時間が経つと、新規作成したウインドー相対ではなくデスクトップ相対のピクセル位置に描画されてしまいました。


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

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

Re:再描画(WM_PAINT)が変

Posted: 2010年6月30日(水) 22:10
by dic
DirectX とあったので、DirectX を使っての描画かと思ったんですが、
上のソースを見るとWIN32AIPを使っての描画のようで、私の勘違いでした

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

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

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

Re:再描画(WM_PAINT)が変

Posted: 2010年6月30日(水) 22:36
by 爺プログラマー
dic ..比類無きプログラマー さん

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

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