2016-07-17 15 views
0

私は、GDIPlusとWindowsヘッダーファイルを使用して画像ボタンを表示することを目標とするWindowsプログラムを作成しています。C++ CAutoPtrアレイにアクセスする際のトラブル

イメージは、グローバルCAutoPtrアレイに添付されています。ボタンのコールバックの中で、ボタンの識別子(GetDlgCtrlID(hWnd))を使用してイメージ配列(imageList)を検索することによってWM_PAINTメッセージを処理します。

imageListの最初の画像でペイントできますが、imageList [2]で次のボタンをペイントしようとすると画像が表示されません。

問題はどこにありますか。なぜimageListの最初のスロットに画像が表示されないのですか?

ありがとうございました!

これは、すべてのボタンメッセージを処理します。

CAutoPtr<Gdiplus::Image> typedef GdiplusImagePtr; 
GdiplusImagePtr imageList[50]; 
Rect imagePositions[50]; 

LRESULT CALLBACK CustomButtonProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 
{ 
    switch (msg) { 
    case WM_CREATE: 
    { 
     // Same as WM_PAINT 
     break; 
    } 
    case WM_PAINT: 
    { 
     PAINTSTRUCT ps; 
     HDC newDC = BeginPaint(hWnd, &ps); 

     Gdiplus::Graphics newGraphics(hWnd); 
     newGraphics.DrawImage(imageList[GetDlgCtrlID(hWnd)], imagePositions[GetDlgCtrlID(hWnd)]); 

     EndPaint(hWnd, &ps); 
     ReleaseDC(hWnd, GetDC(hWnd)); 
     DeleteDC(newDC); 
     break; 
    } 
    return CallWindowProc(customButtonProc, hWnd, msg, wp, lp); 
} 

このコード行を使用して、imageListに画像を添付します。 imageListは他の画像を保持していることを確認しました。私はそれらを表示できません。あなたが別のpalceに一つの場所でGdiplus::ImageGdiplus::Bitmapを使用することはできません

imageList[1].Attach(new Gdiplus::Bitmap(L"TestImage.png")); 

答えて

0
CAutoPtr<Gdiplus::Image> typedef GdiplusImagePtr; 
GdiplusImagePtr imageList[50]; 
imageList[1].Attach(new Gdiplus::Bitmap(L"TestImage.png")); 

このように配列を作成する場合は、CAutoPtrを使用することはできません。さらに、ポインタの配列をグローバル値として宣言しているようです。これはプログラムが終了するまで解放されません。たとえそれが動作しても、このようにする必要はありません。プログラムが終了すると、システムはすべてのメモリを解放します。目標は、プログラムの実行中にメモリ使用量を最小限に抑えることです。

1つのオブジェクトにはCAutoPtrを使用し、アレイにはCAutoPtrArrayを使用してください。しかし、自分で割り当てやクリーンアップを処理する方が簡単で効率的です。例:

std::vector<Gdiplus::Image*> list; 
LRESULT CALLBACK MyProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM) 
{ 
    switch (msg) 
    { 

    case WM_CREATE: 
     list.push_back(new Gdiplus::Image(L"pic1.bmp")); 
     list.push_back(new Gdiplus::Image(L"pic2.bmp")); 
     return TRUE; 

    case WM_NCDESTROY: 
     //free memory here: 
     for (auto e : list) delete e; 
     break; 
    ... 
    } 
} 

case WM_PAINT: 
{ 
    PAINTSTRUCT ps = { 0 }; 
    HDC hdc = BeginPaint(hWnd, &ps); 
    Gdiplus::Graphics graphics(hWnd); 
    graphics.DrawImage(list[0], 0, 0); 
    EndPaint(hWnd, &ps); 
    return 0; 
} 

クリーンアップを描画するための1行だけです。あなたはバージョンVS古いを持っている場合は、カスタム描画ボタンを作成する場合は、ボタンの親でWM_DRAWITEMを処理する必要があり

for (size_t i = 0; i < list.size(); i++) 
    delete list[i]; 

を使用しています。それ以外の場合、サブクラスのWM_PAINTはテーマが無効な場合は機能しません(これはXP/Vista/Win7に適用されます)。

メモリを節約するためにイメージ名のみを保存し、次に読み込み/書き出し/アンロードすることも考えられます。

にも注意してください:

ReleaseDC(hWnd, GetDC(hWnd)); 
DeleteDC(newDC); 

あなたは上記の2行を削除する必要があります。その使用方法に関するドキュメントをお読みください。

関連する問題