あるDLしたのソースに
CPaintDC dc(this);
CDC* pDCMem = new CDC;
pDCMem->CreateCompatibleDC(&dc);
HGDIOBJ hOld;
hOld = pDCMem->SelectObject(m_otOption->GetBoldFont());
pDCMem->SelectObject(hOld);
とあります(抜粋です)
m_otOption->GetBoldFont()はCFont*が返ってきます
CDCクラスのSelectObjectはクラスのポインタが返ってきますが
このソースでは HGDIOBJ に格納しています
こんな事でいいんでしょうか?
HGDIOBJをやめてCFont*にしてしまうか、
やめないで pDCMem->SelectObject((CFont *)hOld);
こうすべきなんでしょうか?
> こんな事でいいんでしょうか?
良くありません!!(^^;
typedef void* HGDIOBJ;
なので、CFont*をHGIDOBJへ代入できてしまうんですね。
SelectObject(hOld)のほうは、
不正なハンドルが来たと思ってエラーになっているはずです。
> HGDIOBJをやめてCFont*にしてしまうか、
この方法が良いと思います。
>やめないで pDCMem->SelectObject((CFont *)hOld);
これでも正しく動きますが、
見る人をさらに混乱させます…。
ありがとうございます
>不正なハンドルが来たと思ってエラーになっているはずです。
NULLが返ってきていました
ついでにすみません。
このバグによって何が起きるか予想はつかないですよね?
リソースが解放されていなければ、リソース不足になるのかな?
実際DLした物を組み込んで作成したソフトで9x系で終了時に落ちる現象があるのですが
これが直接の原因かどうかは判断できないですよね?
デバイスコンテキストに選択された状態ではGDIを削除できないので、
m_otOption->GetBoldFont()が毎回新しいフォントを作っているのであれば、
リソースをどんどん消費して、リソース不足になると思います。
リソース不足になるとメニューやアイコンが表示されなくなったりしますが、
終了時に落ちる直接的な原因にはならないと思います。
リソースを当然獲得できると思って書かれているコードで
落ちる可能性はありますね。
ありがとうございます
m_otOption->GetBoldFont()は毎回新しいフォントは作成していません
m_otOptionのクラスのメンバのアドレスを返します
>終了時に落ちる直接的な原因にはならないと思います。
そうですか。
でもバグなのでHGDIOBJをやめてCFont*に修正中なんですが、
以下のような場合きちんと解放されているのでしょうか?
HGDIOBJ hOldBrush = pDCMem->SelectObject(GetSysColorBrush(COLOR_BTNFACE));
pDCMem->SelectObject(hOldBrush);
MSDN(VC付属の物)には載っていないのですが、
SelectObjectにHGDIOBJを渡せるようです、HGDIOBJが返ってきます
このソースの場合GetSysColorBrushによってHBRUSHを選択させ、HGDIOBJで解放しています
pDCMem->SelectObject(hOldBrush);
で、エラーはでていませんが解放できているのでしょうか?
HBRUSH hOldBrush = (HBRUSH)pDCMem->SelectObject(GetSysColorBrush
(COLOR_BTNFACE));
pDCMem->SelectObject(hOldBrush);
にすべきでしょうか?
何度もすみませんがお願いします。
>このソースの場合GetSysColorBrushによってHBRUSHを選択させ、HGDIOBJで解放しています
> pDCMem->SelectObject(hOldBrush);
>で、エラーはでていませんが解放できているのでしょうか?
横から失礼します。m(__)m
上記のコードは「GDIオブジェクトをもとに戻しておく」ということであって
リークとは直接関係ないと思います。
GetSysColorBrush()のヘルプを読むと「ブラシを削除してはいけない」
と書いてありますので、リークの心配はないと思います。
違っていたら、ご指摘をお願いします。
>GetSysColorBrush()のヘルプを読むと「ブラシを削除してはいけない」
>と書いてありますので、リークの心配はないと思います。
おそらくブラシを Create() しているわけではないので、削除する必要は
なく、リークの心配はないということですね。
はじめまして。
> HBRUSH hOldBrush = (HBRUSH)pDCMem->SelectObject(GetSysColorBrush
>(COLOR_BTNFACE));
> pDCMem->SelectObject(hOldBrush);
>にすべきでしょうか?
正しい動作をしているのであれば、別にこれでも構わないと思いますが、マニュアル掲
載外のものは保証された用法ではないので、個人的には
CBrush* pOldBrush = pDCMem->SelectObject(CBrush::FromHandle(::GetSysColorBrush
(COLOR_BTNFACE)));
pDCMem->SelectObject(pOldBrush);
のようにしておくのが正当なやり方だと思います。
あと、GetSysColorBrush() はウインドウ等を描画するためにシステムが持っているブ
ラシオブジェクトのハンドル(の複製?)を取得するだけなので、Bunさんのおっしゃる
とおり元に戻すだけでよいと思います。
最初の例のように、オブジェクトのポインタとHGDIOBJが混在すると
バグの元になりますから、MFCを使用している場合は、
MFCのクラスだけ使ったほうが安全だと思います。
CBrush::FromHandle()で良いですが、
CBursh::CreateSysColorBrush()なんてのもありますね。
#古いMSDNの説明は完全に間違ってる…。
CBrush brush;
brush.CreateSysColorBrush(COLOR_BTNFACE);
CBrush* pOldBrush = pDCMem->SelectObject(&brush);
...
皆さんありがとうございます。
dairygoodsさんの方法でMFCのクラスだけ使うように変更します
CreateSysColorBrushにCOLOR_BTNFACEを渡すことができるんですね
VC付属のMSDNにはないので、いつのMSDNにのっているのでしょう?
もしかして、他にもこのようにVC付属には無いけど新しいのでは
変更されているのってあるんですかね?