ウインドハンドルとデバイスコンテキストについて – プログラミング – Home

ウインドハンドルとデバイスコンテキスト...
 
通知
すべてクリア

[解決済] ウインドハンドルとデバイスコンテキストについて

固定ページ 1 / 3

vivace98
 vivace98
(@vivace98)
ゲスト
結合: 13年前
投稿: 15
Topic starter  

ウインドウ上でペンによる描画を繰り返すと
プログラムは動き続けているのですが途中から描画ができなくなります
ウインドウハンドルやGetDCで取得したデバイスコンテキストを多用しすぎると
メモリオーバーになることはありますか
よろしくおねがいします

プログラムは
グローバルにウインドハンドルHWND hWndと
デバイスコンテキストHDC hMDC,hDC;と
ペンハンドルHPEN hPen に宣言しており
ウインドハンドルとデバイスコンテキストへの書き込みはそれぞれ一回きりで
そのハンドルと多用しています

解放はデストラクタで行っています

環境はwindows7, visual studio2010, office2010です


引用未解決
トピックタグ
kinoko
 kinoko
(@kinoko)
ゲスト
結合: 13年前
投稿: 4
 

リソースの削除・解放・復元などに抜けがあった際に、
同じく画面の描画が出来なくなった経験があります。

念のためGetDC~ReleaseDCやSelectObjectの変更・復元が、
対になっているか確認してみてください。

HDC hdc = GetDC( hWnd );// HDCを取得 (#1)
HPEN hOldPen = (HPEN)SelectObject( hdc, hPen );// Penを変更 (#2)

// GDIの描画

SelectObject( hdc, hOldPen );// 変更したPenを戻す (#2)
ReleaseDC( hWnd, hdc );// HDCを解放 (#1)

それと、事前にCreatePenなどで生成されたPenオブジェクトが
きちんと対になってDeleteObjectされているかも、
再度確認してみてください。


返信引用
AR2
 AR2
(@ar2)
Estimable Member
結合: 5年前
投稿: 110
 

 簡単にGDIリソースの有無を判定する方法を紹介しますね。
 タスクマネージャのプロセスタブを開いて、GDIオブジェクトのカラムを表示させるよ
うにして、GDIリソースを食いつぶしていないか確認してみてください。


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

確認質問
1:「多用」とはどのくらいか?

2:
>ウインドウハンドルやGetDCで取得したデバイスコンテキストを多用しすぎると

>ウインドハンドルとデバイスコンテキストへの書き込みはそれぞれ一回きりで
>そのハンドルと多用しています
この2つの文の意味するところは・・・
「GetDCやCreatePenなど、GDIオブジェクトの生成などを多用する」
それとも
「GetDCは一回だが、一度とったものに対し何度(描画する必要のあるとき)も、
 利用している」
どっち?

おまけ:Aero切ってみたらどうなる?


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

他の回答者の方たちのおっしゃる通りなのですが、
一部確認したいことがあります。
 1.「一回きりの書き込み」(描画)ですが、WM_PAINTでやってますか。
 2.そうだとするとGetDC()は何のために使っているのでしょう。
一般にWM_PAINTで描画する場合は、BeginPaint()/EndPaint()ですよね。
 3.「hMDC」とはメモリーデバイスコンテキストでしょうか。
  それの、生成と破棄はどのタイミングでやってますでしょうか。
  ちなみにGetDC()はこれのためですかね。
描画ができなくなる原因は色々と考えられます。
GDIリソースの不足(リーク)もその一つですが、他の原因も疑ってみましょう。
虚心坦懐で見直してみてはどうでしょう。


返信引用
vivace98
 vivace98
(@vivace98)
ゲスト
結合: 13年前
投稿: 15
Topic starter  

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

ペンハンドルと、デバイスコンテキストは以下のように解放しています
hDC = GetDC( hWnd );
hPen=CreatePen(PS_SOLID, penbold ,pen.pen_color);
(HPEN)SelectObject(hDC, hPen);
//線を描画
MoveToEx(hDC, MyPoint.OldPoint.x, MyPoint.OldPoint.y, NULL);
LineTo(hDC, MyPoint.NowPoint.x, MyPoint.NowPoint.y);
ReleaseDC( hWnd, hDC );
DeleteObject( hPen );

具体的には私のプログラムは
プレゼンテーション用にパワーポイントを読み込みその上に透明ウインドを表示し、
下線引きを行うものです。
ペンは常に同じ色、太さで描画を行うのですが。
描画を行う度にCreatePenとDeleteObjectを繰り返すひつようはありますか?

描画はWM_MOUSEMOVE内で行っています


返信引用
vivace98
 vivace98
(@vivace98)
ゲスト
結合: 13年前
投稿: 15
Topic starter  

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

確認してみたところ
メモリの食いつぶしは見られませんでした。

今後もタスクマネージャによる確認方法を参考にさせていただきます


返信引用
vivace98
 vivace98
(@vivace98)
ゲスト
結合: 13年前
投稿: 15
Topic starter  

ryoさん
ありがとうがざいます

GetDCは一回生成時に行っており、一度とったものに対し何度(描画する必要のあるとき)も、利用しています

私のプログラムでは
生成した透明ウインドウに下線を引くモードと消しゴム画像上書きして線を消すモード、矢印のアイコンを表示するモードが
あり、それぞれの描画時にデバイスコンテキストを利用しています


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

>hDC = GetDC( hWnd );
>hPen=CreatePen(PS_SOLID, penbold ,pen.pen_color);
>(HPEN)SelectObject(hDC, hPen);
>//線を描画
>MoveToEx(hDC, MyPoint.OldPoint.x, MyPoint.OldPoint.y, NULL);
>LineTo(hDC, MyPoint.NowPoint.x, MyPoint.NowPoint.y);
>ReleaseDC( hWnd, hDC );
>DeleteObject( hPen );

コードがこの通りだとすると、DeleteObject( hPen );の行は効果がありません。
多分、戻り値に0(失敗)が戻っていることでしょう。
正しく動作するようにするには、

HPEN hOldPen = SelectObject(hDC, hPen); //★ここを変更
//線を描画
MoveToEx(hDC, MyPoint.OldPoint.x, MyPoint.OldPoint.y, NULL);
LineTo(hDC, MyPoint.NowPoint.x, MyPoint.NowPoint.y);
SelectObject(hDC, hOldPen); //★ここを挿入
ReleaseDC( hWnd, hDC );
DeleteObject( hPen );

の様に選択を外さなければGDIオブジェクトを削除することはできません。


返信引用
vivace98
 vivace98
(@vivace98)
ゲスト
結合: 13年前
投稿: 15
Topic starter  

仲澤@失業者さんありがとうございます

無駄にGetDC()によりウインドハンドルを取得していたので
WM_PAINTで行うようにしました。

WM_PAINTは透明ウインドウ描画時のみ使用し、
ペンによる描画はWM_MOUSEMOVEメッセージにより行っています。

hMDCは使用していませんでした。

メモリ不足以外の他の原因も考えてみます


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

ん、すれ違ったかな(vv;)。
自分の直前の発言の、ペンの「選択外し」をちゃんとやればOKのような気がします。


返信引用
vivace98
 vivace98
(@vivace98)
ゲスト
結合: 13年前
投稿: 15
Topic starter  

再び仲澤@失業者さんありがとうございます

指示していただいたとおり
コードを挿入しました。

しかし
ウインドウへの描画ができまくなります。

他の原因も考えてみます


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

メモリ不足以外にもリソースの不足と言うのはありえますよ。
GDIリソースのハンドルを開放しそこなった状態で
次のハンドルを取得に行ってしまうと
ハンドル数の上限に達してしまう事になってしまいます。

基本的には、Penの生成と削除、Penを選択すると未選択にするは対になります。

Pen生成(ハンドルの取得)
Penを選択する

諸々描画処理

Penを未選択にする
Pen削除(ハンドルの開放)

この辺はGDIで描画する時の基本なので確認されたほうが良いと思います。
あと、WM_MOUSEMOVEで描画してしまうと他のウインドウが重なったりした時に
消えてしまうと思うのですが、大丈夫ですか?
WM_PAINTにその時の画面の状態を再現する為のコードが必要だと思いますけれど。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

すいません、前の発言は蛇足だったかも。


返信引用
vivace98
 vivace98
(@vivace98)
ゲスト
結合: 13年前
投稿: 15
Topic starter  

PATIOありがとうございます

描画ウインドウは常に最前面に表示するようにしています

他のwindows vistaのパソコンでは問題なく動きました


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

返信する

投稿者名

投稿者メールアドレス

タイトル *

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