在Thread內使用bitmap、jpeg的問題? |
答題得分者是:jow
|
cashyy
高階會員 發表:117 回覆:322 積分:212 註冊:2004-04-30 發送簡訊給我 |
各位您好!
小弟目前寫了一個Thread,但不知是否程式流程有錯,還是BCB的bug,造成小弟所寫的功能有誤! 小弟的程式目的:利用Thread的方式,將秀圖程式顯示在ListView上。 問題點:1.相同的程式碼,不用Thread的方式,功能正常(改成Thread的方式就有問題了!)。 使用Thread的錯誤訊息為:Project Porject1.exe raised exception class EOutOfResources with message '控制碼無效'.Process stopped. Use Step or Run to continue.這是指資源不足,但在沒有使用Thread的情況下,是沒有這個問題了,為何在Thread下使用了bitmap就會有此現象,小弟之前有寫個:使用Thread來擷取桌面,在程式裡面也有用到bitmap,也是擷圖不順利的問題(有時擷圖會都是黑畫面),但不用Thread方式,又可以正常擷取到,跟現在的問題有些類似,所以請各位可以提供小弟方向,小弟有找過很多文章,但都沒發現有類似的問題。 程式碼如下: [code cpp] //--------------------------------------------------------------------------- __fastcall TLoadPictureThread::TLoadPictureThread(AnsiString Path,TListView *listView,TImageList *imageList) : TThread(true) { /* TLoadPictureThread 建構子 */ path = Path; listview = listView; imagelist = imageList; //FreeOnTerminate = true; /* 預設手動釋放物件 */ tag = true; Resume(); //繼續執行緒 } //--------------------------------------------------------------------------- void __fastcall TLoadPictureThread::deleteConstructorsObj() { if(tag) { delete SrcMS; delete JPEG; delete DestBmp; delete SrcBmp; } } //--------------------------------------------------------------------------- void __fastcall TLoadPictureThread::Execute() { /* 宣告縮圖寬度、高度 */ int ThumbWidth = 100; int ThumbHeight = 110; /* 宣告SrcBmp、DestBmp */ //Graphics::TBitmap *SrcBmp,*DestBmp; SrcBmp = new Graphics::TBitmap(); DestBmp = new Graphics::TBitmap(); SrcBmp->PixelFormat = pf24bit; DestBmp->PixelFormat = pf24bit; DestBmp->Width = ThumbWidth; //設定目的圖檔的寬度為縮圖寬度 DestBmp->Height = ThumbHeight; //設定目的圖檔的高度為縮圖高度 /* 宣告pjpeg (include jpeg.hpp) */ //TJPEGImage *JPEG = new TJPEGImage(); JPEG = new TJPEGImage(); /* 宣告SrcMS來讀取圖檔,由SrcMS取檔頭 2 byte並存入str變數 */ //TMemoryStream* SrcMS = new TMemoryStream(); SrcMS = new TMemoryStream(); AnsiString str = ""; /* 設定ImageList的寬、高 */ imagelist->Width = ThumbWidth; imagelist->Height = ThumbHeight; /* 清除imageList、listView */ imagelist->Clear(); listview->Items->Clear(); //TSearchRec sr; AnsiString FileExt = ""; //存放檔案的副檔名 //FindFirst((Path "\\" "*.jpg"),faAnyFile,sr) int done = FindFirst((path "\\" "*.jpg"),faAnyFile, sr); while(done == 0) { //if(!Terminated) //{ try { /* 取得檔案的副檔名,並轉為大寫 */ FileExt = ExtractFileExt(sr.Name).UpperCase(); if(FileExt == ".JPG" || FileExt == ".JPEG") { /* 檢查檔頭前2 byte,並存入str變數 */ SrcMS->LoadFromFile(path "\\" sr.Name); //載入檔案 SrcMS->Size = 2; //2 byte SrcMS->Position = 0; str.SetLength(SrcMS->Size); //設定str(AnsiString)長度 SrcMS->Read(str.c_str(),SrcMS->Size); //由SrcMS(MemoryStream)讀取,並存入str(AnsiString) if(str == "BM") { /* 目前檔案的副檔名為jpg 或jpeg,但實際格式為BMP */ /* 透過 TBitmap 來讀取 */ SrcBmp->LoadFromFile(path "\\" sr.Name); } else { /* 目前檔案的副檔名為jpg 或jpeg,符合jpeg格式 */ /* 透過 TJPEGImage 來讀取 */ JPEG->Performance = jpBestSpeed; //jpBestQuality最佳的品質, jpBestSpeed最佳的速度 JPEG->Scale = jsQuarter; //JPEG->Scale = jsFullSize; JPEG->LoadFromFile(path "\\" sr.Name); SrcBmp->Assign(JPEG); } /* 以下三是將 DestBmp 填滿指定的底色 */ DestBmp->Canvas->CopyMode = cmSrcCopy; DestBmp->Canvas->Brush->Color = clSilver; //縮圖的底色 (圖檔尺寸小於縮圖框尺寸時才會顯示出來) DestBmp->Canvas->FillRect(Rect(0, 0, ThumbWidth, ThumbHeight)); int w = SrcBmp->Width; int h = SrcBmp->Height; int top; int left; /* ====================================== */ /* 如果讀入圖檔的尺寸超出縮圖的指定尺寸,就進行縮小比例的運算 */ if(SrcBmp->Width > ThumbWidth || SrcBmp->Height > ThumbHeight) { top = 0; left = 0; float f = (float)h / w; //取得高度與寬度的比例 w = ThumbWidth; h = f * w; /* 如果計算出來的高度高過縮圖框的高度 */ if(h > ThumbHeight) { h = ThumbHeight; w = h/f; left = (ThumbWidth-w) / 2; } else { top = (ThumbHeight-h) / 2; } /* 大圖需縮小時作此設定會比較美觀 */ SetStretchBltMode(DestBmp->Canvas->Handle, HALFTONE); } else { // 如果讀入圖檔的尺寸小於縮圖的指定尺寸,就計算出居中顯示的位置 left = (ThumbWidth-w) / 2; top = (ThumbHeight-h) / 2; } /* 將讀入的圖檔按照縮圖尺寸繪製到DestBmp上 */ DestBmp->Canvas->CopyRect(Rect(left, top, left w, top h), SrcBmp->Canvas, Rect(0,0,SrcBmp->Width,SrcBmp->Height)); //Item->ImageIndex = ImageList3->Add(DestBmp, NULL); // 將縮圖存入 ImageList /* 將縮圖存入ImageList,並加入到ListItem */ ListItem = listview->Items->Add(); ListItem->Caption = sr.Name; ListItem->ImageIndex = imagelist->Add(DestBmp,NULL); //Synchronize(updateVCL); } } catch(...){ ShowMessage("Error"); } //} done = FindNext(sr); //找尋目錄中的下一個檔案 } FindClose(sr); delete SrcMS; delete JPEG; delete DestBmp; delete SrcBmp; tag = false; } //--------------------------------------------------------------------------- void __fastcall TLoadPictureThread::updateVCL() { //ListItem = listview->Items->Add(); //ListItem->Caption = sr.Name; //ListItem->ImageIndex = imagelist->Add(DestBmp,NULL); } [/code] |
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
|
cashyy
高階會員 發表:117 回覆:322 積分:212 註冊:2004-04-30 發送簡訊給我 |
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
你的問題在於資源被耗盡了,
(1)為了取得 "BM" 來判斷圖檔型態,採用TMemoryStream讀入 整個檔案,雖然 TMemoryStream的 Size有重設成2, 可是用完 並沒有釋放,而造成 Memory Leak. (2)使用 TBitmap *SrcBmp根據檔案型態讀取圖檔, 再把SrcBmp畫到 DestBmp上, 再將DestBmp加入到 TImageList中, 這過程問題出在 SrcBmp再次讀檔時沒 有先釋放掉. (3)TJPEG也要處理. 以下整理一下你的程式碼: [code cpp] //--------------------------------------------------------------------------- #ifndef fMainH #define fMainH //--------------------------------------------------------------------------- #include #include #include #include #include <Forms.hpp><br />#include #include //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: TButton *Button1; TListView *ListView1; TImageList *ImageList1; void __fastcall Button1Click(TObject *Sender); void __fastcall FormCreate(TObject *Sender); private: int ThumbWidth; int ThumbHeight; Graphics::TBitmap* __fastcall CREATE_BITMAP(int width=0, int height=0); Graphics::TBitmap* __fastcall PROCESS_BMP(AnsiString filename); Graphics::TBitmap* __fastcall PROCESS_JPG(AnsiString filename); int __fastcall CHECK_IMAGE_TYPE(AnsiString filename); TStringList* __fastcall GET_FILENAMELIST(bool IsSorted); void __fastcall DRAW_COPYRECT(Graphics::TBitmap *dest, Graphics::TBitmap *src); void __fastcall _ADD_TO_(AnsiString caption, Graphics::TBitmap *dest); public: __fastcall TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif [/code] [code cpp] //--------------------------------------------------------------------------- #include #pragma hdrstop #include "fMain.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { ThumbWidth = 100; ThumbHeight = 110; ImageList1->Width = ThumbWidth; ImageList1->Height = ThumbHeight; ListView1->LargeImages = ImageList1; } //--------------------------------------------------------------------------- Graphics::TBitmap* __fastcall TForm1::CREATE_BITMAP(int width, int height) { Graphics::TBitmap *Result; Result = new Graphics::TBitmap(); Result->PixelFormat = pf24bit; Result->Width = width; Result->Height = height; return Result; } //--------------------------------------------------------------------------- TStringList* __fastcall TForm1::GET_FILENAMELIST(bool IsSorted) { AnsiString path = ".\\DATA\\"; AnsiString filter = ".BMP;.JPG;.JPEG;"; TSearchRec F; AnsiString fn, ext; TStringList *Result = new TStringList(); if(FindFirst(path "*.*", faAnyFile, F)==0) do{ fn = path F.Name.UpperCase(); ext = ExtractFileExt(fn); if((ext!="")&&(filter.Pos(ext ";")>0)) Result->Add(fn); }while(FindNext(F)==0); FindClose(F); Result->Sorted = IsSorted; return Result; } //--------------------------------------------------------------------------- int __fastcall TForm1::CHECK_IMAGE_TYPE(AnsiString filename) { if(!FileExists(filename)) return -1; if(filename.Pos(".BMP")>0)return 0; int Result = -1; if((filename.Pos("JPG")>0)||(filename.Pos("JPEG")>0)){ char s[2]; TFileStream *f = new TFileStream(filename, fmOpenRead); try{ if(f->Read(&s, sizeof(s))==sizeof(2)) if(AnsiString(s).UpperCase()=="BM") Result = 0; else Result = 1; } __finally{ delete f; } } return Result; } //--------------------------------------------------------------------------- void __fastcall TForm1::DRAW_COPYRECT(Graphics::TBitmap *dest, Graphics::TBitmap *src) { if(dest&&src){ TRect sr = Rect(0,0,src->Width,src->Height); TRect dr = Rect(0,0,dest->Width,dest->Height); //Clear dest dest->Canvas->CopyMode = cmSrcCopy; dest->Canvas->Brush->Color = clSilver; dest->Canvas->FillRect(dr); //Copy from src dest->Canvas->CopyRect(dr,src->Canvas,sr); } } //--------------------------------------------------------------------------- void __fastcall TForm1::_ADD_TO_(AnsiString caption, Graphics::TBitmap *dest) { if(dest){ TListItem *ListItem; ListItem = ListView1->Items->Add(); ListItem->Caption = caption; ListItem->ImageIndex = ImageList1->Add(dest, NULL); } } //--------------------------------------------------------------------------- Graphics::TBitmap* __fastcall TForm1::PROCESS_BMP(AnsiString filename) { Graphics::TBitmap *Result = CREATE_BITMAP(ThumbWidth, ThumbHeight); Graphics::TBitmap *src = CREATE_BITMAP(); try{ src->LoadFromFile(filename); DRAW_COPYRECT(Result, src); } __finally{ delete src; } return Result; } //--------------------------------------------------------------------------- Graphics::TBitmap* __fastcall TForm1::PROCESS_JPG(AnsiString filename) { Graphics::TBitmap *Result = CREATE_BITMAP(ThumbWidth, ThumbHeight); Graphics::TBitmap *src = CREATE_BITMAP(); try{ src->LoadFromFile(filename);//產生src方式與bmp不同 DRAW_COPYRECT(Result, src); } __finally{ delete src; } return Result; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ImageList1->Clear(); ListView1->Items->Clear(); //取得所有圖檔檔名(bmp,jpg,jpeg) TStringList *L = GET_FILENAMELIST(true); try{ for(int i=0; i AnsiString fn = L->Strings[i]; if(FileExists(fn)){ switch (CHECK_IMAGE_TYPE(fn)){ case 0: _ADD_TO_(ExtractFileName(fn), PROCESS_BMP(fn)); break; case 1: _ADD_TO_(ExtractFileName(fn), PROCESS_JPG(fn)); break; } } } } __finally{ delete L; } } //--------------------------------------------------------------------------- |
cashyy
高階會員 發表:117 回覆:322 積分:212 註冊:2004-04-30 發送簡訊給我 |
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
TMemoryStream *src; //此時系統記憶體配置4byte給 src 變數本身
src = new TMemoryStream(); //new TMemoryStream()的動作要求系統配置記憶體 //配置的區塊大小 = TMemoryStream->InstanceSize(); //然後Initial成TMemoryStream的型態, 再傳回記憶體位址 //存放在 Src 變數 src->LoadFromFile(); //自檔案讀取資料自然要配置記憶體, 讀入資料後, 資料所在記憶體 //位址傳回, 存放在 TMemoeyStream->Memory 所以src再讀取第二個圖檔時, 從TMemoryStream物件本身以及TMemoryStream->Memory所指向的 記憶體因為失去了指向這塊記憶體的指標(src) ,導致無法被釋放, 因為src已經指向新產生的TMemoryStream物件了. 個人看法謹供參考. ===================引 用 cashyy 文 章=================== 感謝jow大大親自寫了一段範例給小弟參考!確實是因為Src沒釋放的問題,但有一問題想請問大大,我只有在程式的開頭定義Src,直到程式的結尾才delete Src,之前爬了很多文,其它的大大都建議在程式的開頭new個物件,這個物件可以在程式中重覆使用,直到程式的結尾才delete,我也是用這種方法,但在本案例就行不通呢??為什麼在Src一直重覆使用就會出現資源不足??萬分感謝大大的指導! |
cashyy
高階會員 發表:117 回覆:322 積分:212 註冊:2004-04-30 發送簡訊給我 |
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
修改原demo程式, 測試動作以Thread叫用(Button2Click()).
特別注意,Clear的順序, 因為測試時,若以下程式碼順序對調, 未發生OutofResource的狀況,所以要先清除ListView1, 因為 ListView1中的ListItem會以編號 ImageIndex來引用ImageList1中的 Bitmaps. [code cpp] //--------------------------------------------------------------------------- void __fastcall TForm1::ClearAllList() { ListView1->Items->Clear(); ImageList1->Clear(); } //--------------------------------------------------------------------------- [/code] 以下為修正後之程式碼, 經測試執行正常 [code cpp] //--------------------------------------------------------------------------- #ifndef fMainH #define fMainH //--------------------------------------------------------------------------- #include #include #include #include #include <Forms.hpp><br />#include #include //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: TButton *Button1; TListView *ListView1; TImageList *ImageList1; TButton *Button2; void __fastcall Button1Click(TObject *Sender); void __fastcall FormCreate(TObject *Sender); void __fastcall Button2Click(TObject *Sender); private: int ThumbWidth; int ThumbHeight; Graphics::TBitmap* __fastcall CREATE_BITMAP(int width=0, int height=0); void __fastcall DRAW_COPYRECT(Graphics::TBitmap *dest, Graphics::TBitmap *src); public: __fastcall TForm1(TComponent* Owner); TStringList* __fastcall GET_FILENAMELIST(bool IsSorted); int __fastcall CHECK_IMAGE_TYPE(AnsiString filename); void __fastcall ClearAllList(); Graphics::TBitmap* __fastcall PROCESS_BMP(AnsiString filename); Graphics::TBitmap* __fastcall PROCESS_JPG(AnsiString filename); void __fastcall _ADD_TO_(AnsiString caption, Graphics::TBitmap *dest); }; //--------------------------------------------------------------------------- class TMyThread: public TThread { protected: TForm1 *FOwner; Graphics::TBitmap *b; AnsiString fn; void __fastcall Execute(void); void __fastcall ClearAllList(void); void __fastcall _ADD_TO_(void); public: __fastcall TMyThread(TForm1* Owner); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif [code cpp] //--------------------------------------------------------------------------- #include #pragma hdrstop #include "fMain.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { ThumbWidth = 100; ThumbHeight = 110; ImageList1->Width = ThumbWidth; ImageList1->Height = ThumbHeight; ListView1->LargeImages = ImageList1; } //--------------------------------------------------------------------------- Graphics::TBitmap* __fastcall TForm1::CREATE_BITMAP(int width, int height) { Graphics::TBitmap *Result; Result = new Graphics::TBitmap(); Result->PixelFormat = pf24bit; Result->Width = width; Result->Height = height; return Result; } //--------------------------------------------------------------------------- TStringList* __fastcall TForm1::GET_FILENAMELIST(bool IsSorted) { AnsiString path = ".\\DATA\\"; AnsiString filter = ".BMP;.JPG;.JPEG;"; TSearchRec F; AnsiString fn, ext; TStringList *Result = new TStringList(); if(FindFirst(path "*.*", faAnyFile, F)==0) do{ fn = path F.Name.UpperCase(); ext = ExtractFileExt(fn); if((ext!="")&&(filter.Pos(ext ";")>0)) Result->Add(fn); }while(FindNext(F)==0); FindClose(F); Result->Sorted = IsSorted; return Result; } //--------------------------------------------------------------------------- int __fastcall TForm1::CHECK_IMAGE_TYPE(AnsiString filename) { if(!FileExists(filename)) return -1; if(filename.Pos(".BMP")>0)return 0; int Result = -1; if((filename.Pos("JPG")>0)||(filename.Pos("JPEG")>0)){ char s[2]; TFileStream *f = new TFileStream(filename, fmOpenRead); try{ if(f->Read(&s, sizeof(s))==sizeof(2)) if(AnsiString(s).UpperCase()=="BM") Result = 0; else Result = 1; } __finally{ delete f; } } return Result; } //--------------------------------------------------------------------------- void __fastcall TForm1::DRAW_COPYRECT(Graphics::TBitmap *dest, Graphics::TBitmap *src) { if(dest&&src){ TRect sr = Rect(0,0,src->Width,src->Height); TRect dr = Rect(0,0,dest->Width,dest->Height); //Clear dest dest->Canvas->CopyMode = cmSrcCopy; dest->Canvas->Brush->Color = clSilver; dest->Canvas->FillRect(dr); //Copy from src dest->Canvas->CopyRect(dr,src->Canvas,sr); } } //--------------------------------------------------------------------------- void __fastcall TForm1::_ADD_TO_(AnsiString caption, Graphics::TBitmap *dest) { if(dest){ TListItem *ListItem; ListItem = ListView1->Items->Add(); ListItem->Caption = caption; ListItem->ImageIndex = ImageList1->Add(dest, NULL); } } //--------------------------------------------------------------------------- Graphics::TBitmap* __fastcall TForm1::PROCESS_BMP(AnsiString filename) { Graphics::TBitmap *Result = CREATE_BITMAP(ThumbWidth, ThumbHeight); Graphics::TBitmap *src = CREATE_BITMAP(); try{ src->LoadFromFile(filename); DRAW_COPYRECT(Result, src); } __finally{ delete src; } return Result; } //--------------------------------------------------------------------------- Graphics::TBitmap* __fastcall TForm1::PROCESS_JPG(AnsiString filename) { Graphics::TBitmap *Result = CREATE_BITMAP(ThumbWidth, ThumbHeight); Graphics::TBitmap *src = CREATE_BITMAP(); try{ src->LoadFromFile(filename);//產生src方式與bmp不同 DRAW_COPYRECT(Result, src); } __finally{ delete src; } return Result; } //--------------------------------------------------------------------------- void __fastcall TForm1::ClearAllList() { ListView1->Items->Clear(); ImageList1->Clear(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { ClearAllList(); //取得所有圖檔檔名(bmp,jpg,jpeg) TStringList *L = GET_FILENAMELIST(true); try{ for(int i=0; i AnsiString fn = L->Strings[i]; if(FileExists(fn)){ switch (CHECK_IMAGE_TYPE(fn)){ case 0: _ADD_TO_(ExtractFileName(fn), PROCESS_BMP(fn)); break; case 1: _ADD_TO_(ExtractFileName(fn), PROCESS_JPG(fn)); break; } } } } __finally{ delete L; } } //--------------------------------------------------------------------------- __fastcall TMyThread::TMyThread(TForm1* Owner): TThread(true) { FreeOnTerminate = true; FOwner = Owner; Resume(); } //--------------------------------------------------------------------------- void __fastcall TMyThread::Execute(void) { Synchronize(ClearAllList); //取得所有圖檔檔名(bmp,jpg,jpeg) TStringList *L = FOwner->GET_FILENAMELIST(true); try{ for(int i=0; i fn = L->Strings[i]; if(FileExists(fn)){ switch (FOwner->CHECK_IMAGE_TYPE(fn)){ case 0: b = FOwner->PROCESS_BMP(fn); break; case 1: b = FOwner->PROCESS_JPG(fn); break; default: b = NULL; } if(b) Synchronize(_ADD_TO_); } } } __finally{ delete L; } Terminate(); } //--------------------------------------------------------------------------- void __fastcall TMyThread::ClearAllList() { FOwner->ClearAllList(); } //--------------------------------------------------------------------------- void __fastcall TMyThread::_ADD_TO_(void) { FOwner->_ADD_TO_(ExtractFileName(fn), b); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { new TMyThread(this); } //--------------------------------------------------------------------------- |
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
|
cashyy
高階會員 發表:117 回覆:322 積分:212 註冊:2004-04-30 發送簡訊給我 |
jow大大您好!真的感謝您的回覆!
特別注意,Clear的順序, 因為測試時,若以下程式碼順序對調, 未發生OutofResource的狀況,所以要先清除ListView1, 因為 ListView1中的ListItem會以編號 ImageIndex來引用ImageList1中的 Bitmaps. 請問是大大的筆誤嗎?未?會?另外一問,所以之前會發生OutofResource的狀況是因為Clear的順序問題造成的嗎??真沒想到小小一個順序可以造成這麼大的bug,真心感謝jow大大的解答,小弟經驗不足,就算讓我查到死,我也查不出來! |
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
會!
正確用法: void __fastcall TForm1::ClearAllList() { ListView1->Items->Clear(); ImageList1->Clear(); } 至於原來的狀況是否由此造成, 你試試看再告訴我. 因為我上傳的sample圖檔較少,不過測試正常. ===================引 用 cashyy 文 章=================== jow大大您好!真的感謝您的回覆! 特別注意,Clear的順序, 因為測試時,若以下程式碼順序對調, 未發生OutofResource的狀況,所以要先清除ListView1, 因為 ListView1中的ListItem會以編號 ImageIndex來引用ImageList1中的 Bitmaps. 請問是大大的筆誤嗎?未?會?另外一問,所以之前會發生OutofResource的狀況是因為Clear的順序問題造成的嗎??真沒想到小小一個順序可以造成這麼大的bug,真心感謝jow大大的解答,小弟經驗不足,就算讓我查到死,我也查不出來!
編輯記錄
jow 重新編輯於 2007-10-09 01:01:20, 註解 無‧
|
cashyy
高階會員 發表:117 回覆:322 積分:212 註冊:2004-04-30 發送簡訊給我 |
|
cashyy
高階會員 發表:117 回覆:322 積分:212 註冊:2004-04-30 發送簡訊給我 |
jow大大您好!小弟測試過後發現一件事。
測試步驟如下: 資料夾內共有54張JPEG圖,共約3.86MB 問題一:如果用程式單步執行,54張圖完整秀圖無誤。 問題二:如果用程式執行(沒有單步執行情況下),會出現EOutofResources。 問題三:如果直接run執行檔,則會只出現約5張圖而已(自己debug之後發現如果出現EOutofResources,之後的圖檔都不會載入)。 小弟測試之後還是一樣會出現上面三個問題,而且不管ListView->Items->Clear();放在ImageList->Clear();之前或之後都一樣會EOutofResources,這是否是BCB的bug??
編輯記錄
cashyy 重新編輯於 2007-10-09 18:45:34, 註解 無‧
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
發現以下幾個問題:
(1) 這是TImageList的Help中節錄出來的 Image lists are used to efficiently manage large sets of icons or bitmaps. All images in an image list are contained in a single, wide bitmap in screen device format. 所以加入TImageList 的 Bitmap, 在Add()動作後應該要delete掉. 亦即以下程式碼要改為 [code cpp] void __fastcall TForm1::_ADD_TO_(AnsiString caption, Graphics::TBitmap *dest) { if(dest){ TListItem *ListItem; ListItem = ListView1->Items->Add(); ListItem->Caption = caption; ListItem->ImageIndex = ImageList1->Add(dest, NULL); delete dest; } } [/code] (2)圖檔過多時, 每次執行到下列敘述時,每次都會引發 TListView 重畫. 試著用一個TCriticalSection物件隔開, 也沒有效果, 主要是繪圖方面的 資源會有衝突, ListItem->ImageIndex = ImageList1->Add(dest, NULL); 將程式改為下列方式後, 執行就正常. [code c#] //--------------------------------------------------------------------------- void __fastcall TForm1::_ADD_TO_(AnsiString caption, Graphics::TBitmap *dest) { if(dest){ TListItem *ListItem; ListItem = ListView1->Items->Add(); ListItem->Caption = caption; //////ListItem->ImageIndex = ImageList1->Add(dest, NULL); delete dest; } } //--------------------------------------------------------------------------- [/code] 另外可能還要去Trace一下, TImageList對於記憶體是否有所限制?
編輯記錄
jow 重新編輯於 2007-10-09 21:48:11, 註解 無‧
|
cashyy
高階會員 發表:117 回覆:322 積分:212 註冊:2004-04-30 發送簡訊給我 |
===================引 用 jow 文 章=================== 發現以下幾個問題: (1) 這是TImageList的Help中節錄出來的 Image lists are used to efficiently manage large sets of icons or bitmaps. All images in an image list are contained in a single, wide bitmap in screen device format. 所以加入TImageList 的 Bitmap, 在Add()動作後應該要delete掉. 亦即以下程式碼要改為 [code cpp] void __fastcall TForm1::_ADD_TO_(AnsiString caption, Graphics::TBitmap *dest) { if(dest){ TListItem *ListItem; ListItem = ListView1->Items->Add(); ListItem->Caption = caption; ListItem->ImageIndex = ImageList1->Add(dest, NULL); delete dest; } } [/code] (2)圖檔過多時, 每次執行到下列敘述時,每次都會引發 TListView 重畫. 試著用一個TCriticalSection物件隔開, 也沒有效果, 主要是繪圖方面的 資源會有衝突, ListItem->ImageIndex = ImageList1->Add(dest, NULL); 將程式改為下列方式後, 執行就正常. [code c#] //--------------------------------------------------------------------------- void __fastcall TForm1::_ADD_TO_(AnsiString caption, Graphics::TBitmap *dest) { if(dest){ TListItem *ListItem; ListItem = ListView1->Items->Add(); ListItem->Caption = caption; //////ListItem->ImageIndex = ImageList1->Add(dest, NULL); delete dest; } } //--------------------------------------------------------------------------- [/code] 另外可能還要去Trace一下, TImageList對於記憶體是否有所限制? 關於1的話,上篇回覆後,我下線就有加了delete dest;,但沒改ListItem->ImageIndex = ImageList1->Add(dest, NULL);這行。 後來因為覺得會不會是沒有sleep的關係,所以又加了sleep(),但也是沒效果,目前就只能往TImageList方面下手了。 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |