DeleteObjectを使うタイミングについて – プログラミング – Home

DeleteObjectを使うタイミン...
 
通知
すべてクリア

[解決済] DeleteObjectを使うタイミングについて


miya
 miya
(@miya)
ゲスト
結合: 24年前
投稿: 14
Topic starter  

先日、画面表示のエラーについて質問させて頂いた者です。
皆さんのおかげでエラーの原因はリソースリークだったようで、ブラシとフォントを
DeleteObjectで解放することでエラー自体は無くなったのですが、今度はコントロールの
背景色とフォントの変更が行われなくなってしまいました。
多分、DeleteObjectを使う場所が悪いのだと思い、一晩色々試してみたのですがわかりま
せんでした、度々申し訳ありませんがよろしくお願いします。

環境
SDK
windowsXP Pro
vc++6.0

case WM_CREATE:
      hFont = CreateFont
  hEWnd = CreateWindow
SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, 0);
Org_EWnd = (WNDPROC)GetWindowLong(hEWnd48, GWL_WNDPROC);
SetWindowLong(hEWnd48, GWL_WNDPROC, (LONG)FocusProc);


引用未解決
トピックタグ
miya
 miya
(@miya)
ゲスト
結合: 24年前
投稿: 14
Topic starter  

すみません、ソースの貼り付け中に間違って送信してしまいました。

hb = CreateSolidBrush

case WM_CREATE:
  hFont = CreateFont();
hEWnd = CreateWindow();
SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, 0);
Org_EWnd = (WNDPROC)GetWindowLong(hEWnd48, GWL_WNDPROC);
SetWindowLong(hEWnd, GWL_WNDPROC, (LONG)FocusProc);
DeleteObject(hFont);
break;

case WM_CTLCOLOREDIT:
HDC hDC = (HDC)wp;
HWND hCtrl = (HWND)lp;
if(hCtrl == GetDlgItem(Wnd, ID_hEWnd)){
SetBkMode(hDC, TRANSPARENT);
return (LRESULT)hb;}
break;
case WM_COMMAND:
switch(LOWORD(wp)) {

*****************************************
        ここに演算式
*****************************************

hFont = CreateFont;
SetWindowText(hEWnd,演算結果);
SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, 0);
DeleteObject(hFont);
break;

ソースはこんな感じです、投稿ミスで見苦しいスレッドになってしまいました、申し訳あ
りません。


返信引用
s
 s
(@s)
ゲスト
結合: 21年前
投稿: 10
 

hFontが生きているのは

hFont = CreateFont();//ここから
(略)
DeleteObject(hFont); //ここまで

かと

BOOL DeleteObject(HGDIOBJ hObject);
指定された GDI オブジェクト(ペン、ブラシ、フォント、ビットマップ、リージョン、
パレット)を削除し、オブジェクトに関連付けられていたシステムリソースをすべて解放
します。


返信引用
miya
 miya
(@miya)
ゲスト
結合: 24年前
投稿: 14
Topic starter  

hFontが生きてると思う場所でSendMessageを行ったつもりなのですがフォントが変更され
ないみたいです、僕が何かを根本的に間違ってるのでしょうか・・・?


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

とりあえず、WM_SETFONTで使うフォントは、対象となったウィンドウがなくなるまで
DeleteObjectしてはいけないかと思います。

hFontをWndProc関数のstatic変数(もしくはグローバル変数)にして、
WM_DESTROYあたりでDeleteObjectするようにしてみては。

で、WM_COMMANDでフォントを変える場合、hFontをDeleteObjectしてCreateFontを呼ぶよ
うにする。

つまり、

if (hFont) DeleteObject(hFont);
hFont = CreateFont; // ?
SetWindowText(hEWnd,演算結果);
SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, 0);
//DeleteObject(hFont); 不要


返信引用
miya
 miya
(@miya)
ゲスト
結合: 24年前
投稿: 14
Topic starter  

ありがとうございます。

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
static hb = CreateSolidBrush(コントロールの背景色);
static HFONT hFont = CreateFont(フォント);

case WM_CREATE:
hEWnd = CreateWindow();
SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, 0);
Org_EWnd = (WNDPROC)GetWindowLong(hEWnd, GWL_WNDPROC);
SetWindowLong(hEWnd, GWL_WNDPROC, (LONG)FocusProc);
break;

case WM_CTLCOLOREDIT:
HDC hDC = (HDC)wp;
HWND hCtrl = (HWND)lp;
if(hCtrl == GetDlgItem(Wnd, ID_hEWnd)){
SetBkMode(hDC, TRANSPARENT);
return (LRESULT)hb;}
break;

case WM_COMMAND:
switch(LOWORD(wp)) {

*****************************************
        ここに演算式
*****************************************

SetWindowText(hEWnd,演算結果);
SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, 0);
break;

WM_DESTROY
DeleteObject(hb);
DeleteObject(hFont);
break;
}

早速こうしてみたのですが、やっぱりコントロールの中のフォントも背景色も変更されま
せん。
グローバル関数にもしてみたのですが結果は同じでした。
何か間違ってるのでしょうか?

WM_COMMANDではフォントの変更は特にはしないので(内容の同じフォントを作っていまし
た・・・)これで良いと思ったのですが・・・


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

> SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, 0);
の位置は、WM_CREATEの最後
> SetWindowLong(hEWnd, GWL_WNDPROC, (LONG)FocusProc);
の後ろにするのがセオリだと思います。


返信引用
miya
 miya
(@miya)
ゲスト
結合: 24年前
投稿: 14
Topic starter  

>static HBRUSH hb = CreateSolidBrush(コントロールの背景色);
>static HFONT hFont = CreateFont(フォント)

HBRUSH hb = CreateSolidBrush(コントロールの背景色);
HFONT hFont = CreateFont(フォント)

にするとフォントと背景色は変わりましたがリソースリークのエラーが元通りになる見た
いです。

>> SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, 0);
>の位置は、WM_CREATEの最後
>> SetWindowLong(hEWnd, GWL_WNDPROC, (LONG)FocusProc);
>の後ろにするのがセオリだと思います。

その通りに直してみました、ありがとうございます。


返信引用
s
 s
(@s)
ゲスト
結合: 21年前
投稿: 10
 

>SetWindowLong(hEWnd, GWL_WNDPROC, (LONG)FocusProc);
この関数(FocusProc)が何してるかわからないので判断できないが
WM_SETFONTを引っかけてる等があるならそちらも関係ある可能性もあるし
外してみたらどうでっか?

ちなみに関係はないですが
>WM_COMMANDではフォントの変更は特にはしないので
ということは掲載のソースのみで判断するなら
SetWindowText(hEWnd,演算結果);
//SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, 0); ←不要
break;
また破棄ではスタティック変数を使いたくなければ
WM_DESTROY
hFont=(HFONT)SendMessage(hEWnd, WM_GETFONT, 0, 0);
if(hFont) DeleteObject(hFont);
てのも可能

>HBRUSH hb = CreateSolidBrush(コントロールの背景色);
>HFONT hFont = CreateFont(フォント)

>にするとフォントと背景色は変わりましたがリソースリークのエラーが元通りになる見
たいです。

WndProc毎度呼ばれるたびにリソース作ってたら、当然いつかは食いつぶしますよ


返信引用
s
 s
(@s)
ゲスト
結合: 21年前
投稿: 10
 

static WNDPROC Org_EWnd;

LRESULT CALLBACK FocusProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
if(msg==WM_RBUTTONDOWN)
MessageBox(hwnd,テスト,Message,MB_OK|MB_ICONINFORMATION);
else if(msg==WM_SETFONT){
// DebugBreak();
// return 1;
}
return CallWindowProc(Org_EWnd,hwnd,message,wParam,lParam);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HWND hCtrl;
HDC hDC;
static HWND hEWnd;
static HBRUSH hb = (HBRUSH)CreateSolidBrush(RGB(255,0,255));
static HFONT hFont = CreateFont(20, 0, 0, 0, FW_BOLD, FALSE, FALSE, 0,
SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, DEFAULT_PITCH, MS 明朝);
switch (message)
{
case WM_CREATE:
hEWnd = CreateWindow(edit,Test Window,
ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER,
0, 0,200, 100,
hWnd,NULL,hInst,NULL);

SendMessage(hEWnd, WM_SETFONT, (WPARAM)hFont, FALSE);
//(WNDPROC)(LONGLONG)GetWindowLong(hEWnd, GWL_WNDPROC);
Org_EWnd = (WNDPROC)SetWindowLongPtr(hEWnd, GWL_WNDPROC,
(LONG_PTR)FocusProc);

break;
case WM_CTLCOLOREDIT:
hDC = (HDC)wParam;
hCtrl = (HWND)lParam;
if(hCtrl == hEWnd){
SetBkMode(hDC, TRANSPARENT);
return (LRESULT)hb;
}
break;
case WM_DESTROY:
DeleteObject(hb);
DeleteObject(hFont);

PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}


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

横槍になりますけれど、

ウインドウに対してフォントの設定をする時にフォントの変更を
プログラムの実行中に行う必要が無いのであれば、
ウインドウ生成時にフォントの作成と設定を行って置き、
ウインドウ破棄時にフォントの破棄をするべきではないかと思います。
そうすれば、フォントの生成は一回で済みますから。

気をつけるべきなのは設定にしても生成にしても必要最小限に
留めた方がリソースの無駄遣いが防げるという事だと思います。
フォントの変更が必要な場合でも変更時に生成したら
次に変更が必要な状況になるか、ウインドウが破棄されて
フォントが不要になる時まではそのままにしておいて
不要になったら破棄すると言う考え方ですね。
設定したフォントはウインドウが破棄されるか他のフォントに設定しなおされるか
しないと不要にはならないのでその間は保持している必要があるのは既に説明されて
いるとおりです。
GDIに限らずですが、リソースの生成と破棄はプログラミングの中でも
大切な要素の一つなので慎重に対応して慎重すぎると言う事はありません。
まあ、何度かプログラムを不正終了させているうちに段々身については来ますけれど、
意識していないと改善されないので常に意識しておいた方が良いと思います。


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

ちょっと訂正。

> プログラムの実行中に行う必要が無いのであれば、
プログラムの実行中に行う必要が無いのであれば
と言うよりも
アプリを使っている時に動的に変更する必要がないのであれば
と書くべきですね。
そのように読み替えをお願いします。


返信引用
miya
 miya
(@miya)
ゲスト
結合: 24年前
投稿: 14
Topic starter  

みなさん、色々な助言ありがとうございます。

みなさんの言うように1からプログラムを書き直したら上手く動くようになりました。
ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

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