33152


次のように `SelectObject()` の結果を保持して、後で選択しなおすコードをよく見かけます。

[code]

    hDC = BeginPaint(hWnd, &ps);
    hBrush = CreateSolidBrush(RGB(200,200,200));
    hPrevBrush = SelectObject(hDC, hBrush);
    
    Rectangle(hDC, 0, 0, 100, 100);
    
    SelectObject(hDC, hPrevBrush);
    DeleteObject(hBrush);
    EndPaint(hWnd, &ps);
    
[/code]

このような再選択の主な目的は、デバイスコンテキストの状態を元に戻すことで、次の描画に影響を与えないためだと思っています。またデバイスコンテキストより先にBrushを削除するなら、選択を解除しておくべきとも思います。

でも例えばBitmapを作成するなどの用途で、デバイスコンテキストを作成してすぐに破棄してしまう、かつBrushは繰り返し使うので削除せず使いまわしたい、という場合、前述のどちらの理由にも該当せず、再選択する意味がないように思います。

[code]

    hOrigDC = GetDC(hWnd);
    hDC = CreateCompatibleDC(hOrigDC);
    hBitmap = CreateCompatibleBitmap(hDC, 100, 100);
    
    hPrevBitmap = SelectObject(hDC, hBitmap);
    hPrevBrush = SelectObject(hDC, hBrush);
    
    Rectangle(hDC, 0, 0, 100, 100);
    
    SelectObject(hDC, hPrevBrush); // これは必要？？
    SelectObject(hDC, hPrevBitmap); // これは必要？？
    DeleteDC(hDC);
    ReleaseDC(hWnd, hOrigDC);
    
[/code]

MSDNには[「アプリケーションは新しいオブジェクトを使い終えたら、必ず元の（既定）オブジェクトに置き換えるべきです。」](https://msdn.microsoft.com/ja-
jp/library/cc410576.aspx)とあるので、このような場合でも元のオブジェクトを選択しなおした方がいいのだとは思いますが、その理由はなぜでしょうか？


CC BY-SA 3.0
2017-03-03T12:11:03.060
33072
2017-03-07T00:52:03.733
20204
question
winapi
SelectObjectした後で元のオブジェクトを選択しなおすべきなのはなぜ？


公式の説明は見たことがありませんが、ソフトウェアエンジニアとしての経験から察すると、「元のオブジェクトをただしく開放するため」だと思われます。

通常はデバイスコンテキストの開放処理の中で選択されているオブジェクトも開放するのだと想像できますが、もし元のオブジェクトに戻すための
`SelectObject()`
がないと、それらのオブジェクトを誰も開放しなくなくなります。アプリケーションが選択していない「元のオブジェクト」を何か他の用途に使っているかもしれないので、システム側では勝手に開放することができません。


CC BY-SA 3.0
2017-03-06T18:25:56.640
33149
2017-03-06T18:25:56.640
3475
33072
answer


なぜ必要かという疑問への直接回答ではありませんが、MSDNには「正しくリストア・削除しないとパフォーマンス問題になり得る」と言及されています。

MSDN [Operations on Graphic Objects](https://msdn.microsoft.com/en-
us/library/dd162753.aspx) ページ下部より引用：

> Each of these functions returns a handle identifying a new object. After an
> application retrieves a handle, it must call the `SelectObject` function to
> replace the default object. However, the application should save the handle
> identifying the default object and use this handle to replace the new object
> when it is no longer needed. **When the application finishes drawing with
> the new object, it must restore the default object by calling
> the`SelectObject` function and then delete the new object by calling the
> `DeleteObject` function. Failing to delete objects causes serious
> performance problems.**


CC BY-SA 3.0
2017-03-07T00:52:03.733
33152
2017-03-07T00:52:03.733
49
33072
answer