Форум » GUI » Требуется помощь при освобождении ресурсов GdiPlus » Ответить

Требуется помощь при освобождении ресурсов GdiPlus

gfilatov2002: Вниманию Петра, Павла и всех, кто работал с библиотекой GdiPlus Я переписал модуль c_image.c для поддержки вывода PNG, TIF и ICO в элементе управления Image, основываясь на адаптации GdiPlus, выполненной Клаудио Сото для официального релиза HMG 3.1.1 Все заявленное работает, но при этом происходит утечка Bitmap-ресурсов при каждом изменении картинки в программе. Для освобождения Bitmap-ресурсов я использовал GdiPlus-функцию GdipDisposeImage(), но это не помогло Поэтому требуется помощь знатоков Загрузить модуль c_image.c для проверки можно отсюда

Ответов - 5

Andrey: gfilatov2002 пишет: Вниманию Петра, Павла и всех, кто работал с библиотекой GdiPlus Народ ! Помогите пожалуйста Григорию !!! Уж очень хочется нормальных картинок в МиниГуи...

santy: Григорий, выставите ещё раз исходник и если есть тестовый пример. Спасибо.

gfilatov2002: santy пишет: выставите ещё раз исходник и если есть тестовый пример Загрузить модуль c_image.c для проверки можно отсюда Простой пример ниже показывает утечку ресурсов при обновлении PNG картинки в цикле [pre]#include "hmg.ch" Function Main DEFINE WINDOW Win_1 ; AT 0,0 ; WIDTH 640 HEIGHT 480 ; TITLE 'Main Window' ; ICON 'WORLD' ; MAIN @ 200,140 IMAGE Image_1 ; PICTURE 'img.gif' ; WIDTH 200 ; HEIGHT 200 @ 10 ,10 BUTTON Button_1 CAPTION "Set png" ACTION test() WIDTH 100 HEIGHT 30 @ 10 ,110 BUTTON Button_2 CAPTION "Set jpg" ACTION Win_1.Image_1.Picture := "img.jpg" WIDTH 100 HEIGHT 30 @ 10 ,210 BUTTON Button_3 CAPTION "Set ico" ACTION Win_1.Image_1.Picture := "img.ico" WIDTH 100 HEIGHT 30 @ 10 ,310 BUTTON Button_4 CAPTION "Set wmf" ACTION Win_1.Image_1.Picture := "img.wmf" WIDTH 100 HEIGHT 30 @ 10 ,410 BUTTON Button_5 CAPTION "Set cur" ACTION Win_1.Image_1.Picture := "img.cur" WIDTH 100 HEIGHT 30 @ 10 ,510 BUTTON Button_6 CAPTION "Set bmp" ACTION Win_1.Image_1.Picture := "demo.bmp" WIDTH 100 HEIGHT 30 END WINDOW ACTIVATE WINDOW Win_1 Return Nil func test local i for i:=1 to 1000 Win_1.Image_1.Picture := "img.png" do events next retu nil [/pre] Я уже написал об этой проблеме автору этой модификации и он подтвердил наличие этой проблемы для PNG-файлов


santy: ошибка при скачивании : Ошибка 404. Документ не найден.

gfilatov2002: santy пишет: ошибка при скачивании Поскольку файл c_image.c небольшой по размеру, выложил его здесь [pre]/*---------------------------------------------------------------------------- MINIGUI - Harbour Win32 GUI library source code Copyright 2002-2010 Roberto Lopez <harbourminigui@gmail.com> http://harbourminigui.googlepages.com/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this software; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). As a special exception, you have permission for additional uses of the text contained in this release of Harbour Minigui. The exception is that, if you link the Harbour Minigui library with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. Your use of that executable is in no way restricted on account of linking the Harbour-Minigui library code into it. Parts of this project are based upon: "Harbour GUI framework for Win32" Copyright 2001 Alexander S.Kresin <alex@belacy.belgorod.su> Copyright 2001 Antonio Linares <alinares@fivetech.com> www - http://harbour-project.org "Harbour Project" Copyright 1999-2013, http://harbour-project.org/ "WHAT32" Copyright 2002 AJ Wos <andrwos@aust1.net> "HWGUI" Copyright 2001-2009 Alexander S.Kresin <alex@belacy.belgorod.su> ---------------------------------------------------------------------------*/ #ifndef CINTERFACE #define CINTERFACE #endif #define _WIN32_IE 0x0500 #ifdef __POCC__ #define _WIN32_WINNT 0x0500 #else #define _WIN32_WINNT 0x0400 #endif #include <windows.h> #include <commctrl.h> #include "olectl.h" #include "hbapi.h" #include "hbapiitm.h" #include "hbvm.h" HBITMAP loadolepicture( char * filename, int width, int height, HWND handle, int scalestrech, int whitebackground, int transparent ); LRESULT APIENTRY PictSubClassFunc( HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam ); static WNDPROC LabelOldWndProc; HB_FUNC( INITIMAGE ) { HWND hWnd; HWND hWndParent = ( HWND ) hb_parnl( 1 ); int Style = WS_CHILD | SS_BITMAP; if( ! hb_parl( 5 ) ) Style |= WS_VISIBLE; if( hb_parl( 6 ) || hb_parl( 7 ) ) Style |= SS_NOTIFY; hWnd = CreateWindowEx( 0, "static", NULL, Style, hb_parni( 3 ), hb_parni( 4 ), 0, 0, hWndParent, ( HMENU ) hb_parni( 2 ), GetModuleHandle( NULL ), NULL ); if( hb_parl( 7 ) ) LabelOldWndProc = ( WNDPROC ) SetWindowLong( hWnd, GWL_WNDPROC, ( LONG ) PictSubClassFunc ); hb_retnl( ( LONG ) hWnd ); } HB_FUNC( C_SETPICTURE ) { HBITMAP hBitmap; if( hb_parclen( 2 ) == 0 ) hb_retnl( ( LONG ) NULL ); hBitmap = loadolepicture( ( char * ) hb_parc( 2 ), hb_parni( 3 ), hb_parni( 4 ), ( HWND ) hb_parnl( 1 ), hb_parni( 5 ), hb_parni( 6 ), hb_parni( 7 ) ); if( hBitmap != NULL ) SendMessage( ( HWND ) hb_parnl( 1 ), ( UINT ) STM_SETIMAGE, ( WPARAM ) IMAGE_BITMAP, ( LPARAM ) hBitmap ); hb_retnl( ( LONG ) hBitmap ); } #define _OLD_STYLE 0 LRESULT APIENTRY PictSubClassFunc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) { TRACKMOUSEEVENT tme; static PHB_SYMB pSymbol = NULL; static BOOL bMouseTracking = FALSE; long r = 0; #if _OLD_STYLE BOOL bCallUDF = FALSE; #endif if( Msg == WM_MOUSEMOVE || Msg == WM_MOUSELEAVE ) { if( Msg == WM_MOUSEMOVE ) { if( bMouseTracking == FALSE ) { tme.cbSize = sizeof( TRACKMOUSEEVENT ); tme.dwFlags = TME_LEAVE; tme.hwndTrack = hWnd; tme.dwHoverTime = HOVER_DEFAULT; if( _TrackMouseEvent( &tme ) == TRUE ) { #if _OLD_STYLE bCallUDF = TRUE; #endif bMouseTracking = TRUE; } #if _OLD_STYLE } else { bCallUDF = FALSE; #endif } } else { #if _OLD_STYLE bCallUDF = TRUE; #endif bMouseTracking = FALSE; } #if _OLD_STYLE if( bCallUDF == TRUE ) { #endif if( ! pSymbol ) pSymbol = hb_dynsymSymbol( hb_dynsymGet( "OLABELEVENTS" ) ); if( pSymbol && hb_vmRequestReenter() ) { hb_vmPushSymbol( pSymbol ); hb_vmPushNil(); hb_vmPushLong( ( LONG ) hWnd ); hb_vmPushLong( Msg ); hb_vmPushLong( wParam ); hb_vmPushLong( lParam ); hb_vmDo( 4 ); r = hb_parnl( -1 ); hb_vmRequestRestore(); } #if _OLD_STYLE } #endif return ( r != 0 ) ? r : CallWindowProc( LabelOldWndProc, hWnd, 0, 0, 0 ); } bMouseTracking = FALSE; return CallWindowProc( LabelOldWndProc, hWnd, Msg, wParam, lParam ); } #undef _OLD_STYLE /*------------------------------------------------------------------------- The following functions are taken from the graphics library Bos Taurus. Bos Taurus, (c) 2012 by Dr. Claudio Soto <srvet@adinet.com.uy> ---------------------------------------------------------------------------*/ //********************************************************************************************************************* // __bt_LoadFileFromResources (FileName, TypeResource) ---> Return hGlobalAlloc //********************************************************************************************************************* static HGLOBAL __bt_LoadFileFromResources( char * FileName, char * TypeResource ) { HRSRC hResourceData; HGLOBAL hGlobalAlloc, hGlobalResource; LPVOID lpGlobalAlloc, lpGlobalResource; DWORD nFileSize; hResourceData = FindResource( NULL, FileName, TypeResource ); if( hResourceData == NULL ) return NULL; hGlobalResource = LoadResource( NULL, hResourceData ); if( hGlobalResource == NULL ) return NULL; lpGlobalResource = LockResource( hGlobalResource ); if( lpGlobalResource == NULL ) return NULL; nFileSize = SizeofResource( NULL, hResourceData ); hGlobalAlloc = GlobalAlloc( GHND, nFileSize ); if( hGlobalAlloc == NULL ) { FreeResource( hGlobalResource ); return NULL; } lpGlobalAlloc = GlobalLock( hGlobalAlloc ); CopyMemory( lpGlobalAlloc, lpGlobalResource, ( SIZE_T ) nFileSize ); GlobalUnlock( hGlobalAlloc ); FreeResource( hGlobalResource ); return hGlobalAlloc; } //********************************************************************************************************************* // __bt_LoadFileFromDisk (FileName) ---> Return hGlobalAlloc //********************************************************************************************************************* static HGLOBAL __bt_LoadFileFromDisk( char * FileName ) { HGLOBAL hGlobalAlloc; LPVOID lpGlobalAlloc; HANDLE hFile; DWORD nFileSize; DWORD nReadByte; hFile = CreateFile( FileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile == INVALID_HANDLE_VALUE ) return NULL; nFileSize = GetFileSize( hFile, NULL ); if( nFileSize == INVALID_FILE_SIZE ) { CloseHandle( hFile ); return NULL; } hGlobalAlloc = GlobalAlloc( GHND, nFileSize ); if( hGlobalAlloc == NULL ) { CloseHandle( hFile ); return NULL; } lpGlobalAlloc = GlobalLock( hGlobalAlloc ); ReadFile( hFile, lpGlobalAlloc, nFileSize, &nReadByte, NULL ); GlobalUnlock( hGlobalAlloc ); CloseHandle( hFile ); return hGlobalAlloc; } //************************************************************************************************************* // __bt_LoadGDIPlusPicture (FileName, TypePicture) ---> Return hBitmap (Load GIF, JPG, TIFF and PNG image) //************************************************************************************************************* // Begin GDIPLUS Definitions typedef enum GpStatus { Ok = 0, GenericError = 1, InvalidParameter = 2, OutOfMemory = 3, ObjectBusy = 4, InsufficientBuffer = 5, NotImplemented = 6, Win32Error = 7, WrongState = 8, Aborted = 9, FileNotFound = 10, ValueOverflow = 11, AccessDenied = 12, UnknownImageFormat = 13, FontFamilyNotFound = 14, FontStyleNotFound = 15, NotTrueTypeFont = 16, UnsupportedGdiplusVersion = 17, GdiplusNotInitialized = 18, PropertyNotFound = 19, PropertyNotSupported = 20, ProfileNotFound = 21 } GpStatus; #define WINGDIPAPI __stdcall #define GDIPCONST const typedef void GpBitmap; typedef void * DebugEventProc; typedef struct GdiplusStartupInput { UINT32 GdiplusVersion; DebugEventProc DebugEventCallback; BOOL SuppressBackgroundThread; BOOL SuppressExternalCodecs; } GdiplusStartupInput; typedef GpStatus WINGDIPAPI ( *NotificationHookProc )( ULONG_PTR * token ); typedef VOID WINGDIPAPI ( *NotificationUnhookProc )( ULONG_PTR token ); typedef struct GdiplusStartupOutput { NotificationHookProc NotificationHook; NotificationUnhookProc NotificationUnhook; } GdiplusStartupOutput; typedef ULONG ARGB; typedef GpStatus ( WINGDIPAPI * Func_GdiPlusStartup )( ULONG_PTR *, GDIPCONST GdiplusStartupInput *, GdiplusStartupOutput * ); typedef VOID ( WINGDIPAPI * Func_GdiPlusShutdown )( ULONG_PTR ); typedef GpStatus ( WINGDIPAPI * Func_GdipCreateBitmapFromStream )( IStream *, GpBitmap ** ); typedef GpStatus ( WINGDIPAPI * Func_GdipCreateHBITMAPFromBitmap )( GpBitmap *, HBITMAP *, ARGB ); typedef GpStatus ( WINGDIPAPI * Func_GdipDisposeImage )( GpBitmap * ); // End GDIPLUS Definitions static HBITMAP __bt_LoadGDIPlusPicture( char * FileName, char * TypePictureResource ) { IStream * iStream; HBITMAP hBitmap; HGLOBAL hGlobalAlloc; GpBitmap * pGpBitmap; VOID * GdiPlusHandle; ULONG GdiPlusToken; ARGB BkColor; GdiplusStartupInput GDIPlusStartupInput; Func_GdiPlusStartup GdiPlusStartup; Func_GdiPlusShutdown GdiPlusShutdown; Func_GdipCreateBitmapFromStream GdipCreateBitmapFromStream; Func_GdipCreateHBITMAPFromBitmap GdipCreateHBITMAPFromBitmap; Func_GdipDisposeImage GdipDisposeImage; GdiPlusHandle = LoadLibrary( "GdiPlus.dll" ); if( GdiPlusHandle == NULL ) return NULL; GdiPlusStartup = ( Func_GdiPlusStartup ) GetProcAddress( GdiPlusHandle, "GdiplusStartup" ); GdiPlusShutdown = ( Func_GdiPlusShutdown ) GetProcAddress( GdiPlusHandle, "GdiplusShutdown" ); GdipCreateBitmapFromStream = ( Func_GdipCreateBitmapFromStream ) GetProcAddress( GdiPlusHandle, "GdipCreateBitmapFromStream" ); GdipCreateHBITMAPFromBitmap = ( Func_GdipCreateHBITMAPFromBitmap ) GetProcAddress( GdiPlusHandle, "GdipCreateHBITMAPFromBitmap" ); GdipDisposeImage = ( Func_GdipDisposeImage ) GetProcAddress( GdiPlusHandle, "GdipDisposeImage" ); if( GdiPlusStartup == NULL || GdiPlusShutdown == NULL || GdipCreateBitmapFromStream == NULL || GdipCreateHBITMAPFromBitmap == NULL || GdipDisposeImage == NULL ) { FreeLibrary( GdiPlusHandle ); return NULL; } GDIPlusStartupInput.GdiplusVersion = 1; GDIPlusStartupInput.DebugEventCallback = NULL; GDIPlusStartupInput.SuppressBackgroundThread = FALSE; GDIPlusStartupInput.SuppressExternalCodecs = FALSE; if( GdiPlusStartup( &GdiPlusToken, &GDIPlusStartupInput, NULL ) ) { FreeLibrary( GdiPlusHandle ); return NULL; } if( TypePictureResource != NULL ) hGlobalAlloc = __bt_LoadFileFromResources( FileName, TypePictureResource ); else hGlobalAlloc = __bt_LoadFileFromDisk( FileName ); if( hGlobalAlloc == NULL ) return NULL; iStream = NULL; if( CreateStreamOnHGlobal( hGlobalAlloc, FALSE, &iStream ) == S_OK ) { hBitmap = NULL; BkColor = 0xFF000000UL; GdipCreateBitmapFromStream( iStream, &pGpBitmap ); GdipCreateHBITMAPFromBitmap( pGpBitmap, &hBitmap, BkColor ); GdipDisposeImage( pGpBitmap ); iStream->lpVtbl->Release( iStream ); } GdiPlusShutdown( GdiPlusToken ); FreeLibrary( GdiPlusHandle ); GlobalFree( hGlobalAlloc ); return hBitmap; } //******************************************************************************************************************************** //* loadolepicture() ---> Return hBitmap (Load: BMP, GIF, JPG, TIF, WMF, PNG, ICO, CUR) //******************************************************************************************************************************** HBITMAP loadolepicture( char * filename, int width, int height, HWND handle, int scalestrech, int whitebackground, int transparent ) { IStream * iStream; IPicture * iPicture = NULL; HGLOBAL hGlobalAlloc = ( HGLOBAL ) NULL; RECT rect, rect2; HBITMAP hBitmap_New, hBitmap; BITMAP bm; LONG lWidth, lHeight; HDC hDC, memDC1, memDC2; UINT fuLoad = ( transparent == 0 ) ? LR_CREATEDIBSECTION : LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT; if( width == 0 && height == 0 ) GetClientRect( handle, &rect ); else SetRect( &rect, 0, 0, width, height ); SetRect( &rect2, 0, 0, rect.right, rect.bottom ); hBitmap = ( HBITMAP ) LoadImage( GetModuleHandle( NULL ), filename, IMAGE_BITMAP, 0, 0, fuLoad ); if( hBitmap == NULL ) hBitmap = ( HBITMAP ) LoadImage( NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | fuLoad ); if( hBitmap == NULL ) { hBitmap = __bt_LoadGDIPlusPicture( filename, "PNG" ); if( hBitmap == NULL ) { hGlobalAlloc = __bt_LoadFileFromResources( filename, "GIF" ); if( hGlobalAlloc == NULL ) hGlobalAlloc = __bt_LoadFileFromResources( filename, "JPG" ); if( hGlobalAlloc == NULL ) hGlobalAlloc = __bt_LoadFileFromResources( filename, "WMF" ); if( hGlobalAlloc == NULL ) hGlobalAlloc = __bt_LoadFileFromResources( filename, "ICO" ); // To load an ICON as an IMAGE from the resourses define in the resources as ICO. // If set to ICON in the resourses can not be loaded as an image. if( hGlobalAlloc == NULL ) hGlobalAlloc = __bt_LoadFileFromResources( filename, "CUR" ); // To load an CURSOR as an IMAGE from the resourses define in the resources as CUR. // If set to CURSOR in the resourses can not be loaded as an image. if( hGlobalAlloc == NULL ) hGlobalAlloc = __bt_LoadFileFromDisk( filename ); if( hGlobalAlloc != NULL ) { CreateStreamOnHGlobal( hGlobalAlloc, TRUE, &iStream ); OleLoadPicture( iStream, 0, TRUE, &IID_IPicture, ( LPVOID * ) &iPicture ); if( iPicture != NULL ) { iPicture->lpVtbl->get_Width( iPicture, &lWidth ); iPicture->lpVtbl->get_Height( iPicture, &lHeight ); } } if( iPicture == NULL ) { if( hGlobalAlloc != NULL ) GlobalFree( hGlobalAlloc ); hBitmap = __bt_LoadGDIPlusPicture( filename, NULL ); } } } if( hBitmap == NULL && iPicture == NULL ) return NULL; hDC = GetDC( handle ); memDC2 = CreateCompatibleDC( hDC ); memDC1 = CreateCompatibleDC( hDC ); if( hBitmap != NULL ) { GetObject( hBitmap, sizeof( BITMAP ), &bm ); lWidth = bm.bmWidth; lHeight = bm.bmHeight; SelectObject( memDC1, hBitmap ); } if( scalestrech == 0 ) { if( ( int ) lWidth * rect.bottom / lHeight <= rect.right ) rect.right = ( int ) lWidth * rect.bottom / lHeight; else rect.bottom = ( int ) lHeight * rect.right / lWidth; } rect.left = ( int ) ( width - rect.right ) / 2; rect.top = ( int ) ( height - rect.bottom ) / 2; hBitmap_New = CreateCompatibleBitmap( hDC, width, height ); SelectObject( memDC2, hBitmap_New ); if( whitebackground == 1 ) FillRect( memDC2, &rect2, ( HBRUSH ) GetStockObject( WHITE_BRUSH ) ); else FillRect( memDC2, &rect2, ( HBRUSH ) GetSysColorBrush( COLOR_BTNFACE ) ); if( iPicture != NULL ) { iPicture->lpVtbl->Render( iPicture, memDC2, rect.left, rect.top, rect.right, rect.bottom, 0, lHeight, lWidth, -lHeight, NULL ); iPicture->lpVtbl->Release( iPicture ); GlobalFree( hGlobalAlloc ); } else { SetStretchBltMode( memDC2, COLORONCOLOR ); StretchBlt( memDC2, rect.left, rect.top, rect.right, rect.bottom, memDC1, 0, 0, lWidth, lHeight, SRCCOPY ); DeleteObject( hBitmap ); } DeleteDC( memDC1 ); DeleteDC( memDC2 ); ReleaseDC( handle, hDC ); return hBitmap_New; }[/pre]



полная версия страницы