質問: ### 質問 デバイスコンテキストの取得は`BeginPaint`や`GetDC`などがありますが私が以前書いたWinAPI BITMAPを読み込んでBITMAPの描画・UI (正しいかはわかりませんが)のような`WM_PAINT`外部で`HDC`をCompatibleさせたいときには`BegonPaint`は使えないだろうと`GetDC`を`WM_CREATE`で用いて上のスコープでstatic HDCに代入しました.しかし`BeginPaint/EndPaint`でDCハンドルは`WM_PAINT`内のスコープで完結していますが先ほどのほうだとHDCを長い間保持していることになります.MSDN : GetDC functionのRemarksには > > After painting with a common DC, the ReleaseDC function must be called to release the DC. > > > と書かれています.`GetDC`で取得したハンドルはCompatibleさせるときまで生かしておかなければならないですが解放しなくていいのでしょうか? また先ほどの提示したコードは`GetDC`を使い`InvalidRect/ValidRect`で領域の有効無効を切り替えているつもりですがファイルドロップで違う画像を読み込んだ時,前の画像が再描画で消えません.`BeginPaint`は`InvalidRect`で生じた無効領域を塗りなおすと思いますが`GetDC`では領域全体の再描画はなされないのでしょうか ### 補足情報 Windows10 Pro VisualStudio2019 Community
回答: 先の回答者様より既に指摘されていましたが、質問が閉じていなかったので質疑応答をうながす意味も含め、回答します。 > > GetDCで取得したハンドルはCompatibleさせるときまで生かしておかなければならないですが解放しなくていいのでしょうか? > > > いえ、`ReleaseDC`で解放しなければなりません。アプリケーションが終了すれば自動的に解放されるでしょうが、作法としてはNGです。 Win32ネイティブAPIのウィンドウアプリケーションのプログラミングの一般的作法としては、`GetDC`で取得したデバイスコンテキストを保存して使いまわすことは余り無く、ウィンドウプロシージャ内において、各メッセージのハンドリング中に`GetDC`~`ReleaseDC`で完結させることが多いです。多くのサンプルプログラムもそのようになっています。絶対にそうしなければならないかと問われると自信は無いですが、実際、マイクロソフトのMSDNのサンプルDrawing at Timed Intervalsでは使いまわしています。ただ、あろうことか`ReleaseDC`で解放すらしていませんが。サンプルプログラム自体にバグや問題があることもあるので、この辺り、描画関連処理に疎い私の知識では、ちょっとどれを信じて良いか分かりません。 確実に言えることは、`GetDC`で取得するデバイスコンテキストは通常、ウィンドウに関連付けられたWindowsのGDIオブジェクトであり、`ReleaseDC`で解放しないとリソースリークとなり、枯渇します。実際、以下のようなコードを書くとGDIオブジェクトが解放されないままになります。これは、特に常駐モノのプログラムでは許されないコードだと思います。尚、実行中のアプリケーションが利用しているGDIオブジェクトの個数は、タスクマネージャーで簡単に確認できます。 ``` for (int i = 0; i < 100; i++) { char s[32]; HDC hdc = GetDC(hDlg); // まかり間違ってもコンパイル時の最適化でコードが消えないよう、とにかくhdcを使う wsprintfA(s, "hdc=%X\n", hdc); OutputDebugStringA(s); } ``` > > BeginPaintはInvalidRectで生じた無効領域を塗りなおすと思いますがGetDCでは領域全体の再描画はなされないのでしょうか > > > 通常、`InvalidateRect`で無効化された領域を描画する場合は、無効化領域ができたことによって発生する`WM_PAINT`メッセージ受信時の処理で、`BeginPaint`で返る`HDC`を使うのが正規の方法です。Weaponさんの例では、ウィンドウプロシージャのごく初期に`GetDC`で取得したデバイスコンテキストを使おうとしていることで、その時に使うべきデバイスコンテキストが適切ではない可能性があることも相まって、、要望どおりの動作をしていないものだと思われます。これに関して、先のご質問#183738 - WinAPI BITMAPを読み込んでBITMAPの描画・UIのコードでプロジェクトを作成し、動作確認を試みましたが、当方で試したビットマップファイルが不適切だったのか、動作しなかったので意見を述べるにとどめます。